Search code examples
node.jsimage-uploadingimage-compressionmulter

Combine multer and tinypng API in node


does anyone know how to use tinyPNG's API with multer? The docs seem deceptively simple:

var source = tinify.fromFile("unoptimized.jpg");
source.toFile("optimized.jpg");

though there's no clear indication of where this is meant to go, especially in something as convoluted as this:

var storage =  multer.diskStorage(
    {
      destination: function (req, file, callback) {
        callback(null, './uploads');
      },

      filename: function (req, file, callback) {
        //use date to guarantee name uniqueness
        callback(null, file.originalname + '-' + Date.now());
      }
    }
);

//.any() allows multiple file uploads
var upload = multer({ storage : storage}).any()

app.post('/api/photo', function(req,res){

    upload(req,res,function(err) {

        if(err) {
            return res.end("Error uploading file.");
        }

        res.end("File is uploaded");
    });
});

Where am I meant to "intercept" the file uploaded by multer so that I can compress it with tinyPNG?

Thanks in advance for the help!


Solution

  • Use following basic sample that changes uploaded photo/gallery files:

    // Import express and multer.
    var express = require('express');
    var multer  = require('multer');
    
    // Setup upload.
    var upload = multer({ dest: 'uploads/' });
    var multipleFiles = upload.fields([{ name: 'photo', maxCount: 1 }, 
                                       { name: 'gallery', maxCount: 8 }]);
    
    // Setup tinify.
    var tinify = require("tinify");
    tinify.key = "YOUR_API_KEY";
    
    // Get request handler for '/' path.
    var app = express();
    app.get('/', function (req, res) {
        res.setHeader("Content-Type", "text/html");
        res.end(
            "<form action='/api/photo' method='post' enctype='multipart/form-data'>" +
                "<input type='file' name='photo' />" +
                "<input type='file' name='gallery' multiple/>" +
                "<input type='submit' />" +
            "</form>"
        );
    });
    
    // Upload file handler with '/api/photo' path.
    app.post('/api/photo', multipleFiles, function (req, res) {
        req.files['gallery'].forEach(function(file) {
           // Your logic with tinify here.
           var source = tinify.fromFile(file.path);
           source.toFile(file.path + "_optimized.jpg");
        });
    
        res.end("UPLOAD COMPLETED!");
    });
    

    Feel free to change express middleware how you need it, just make sure you use upload.fields and authenticate using tinify.key = "YOUR_API_KEY";