onda47
onda47

Reputation: 636

Efficient way to read file in NodeJS

I am receiving an image file sent from an Ajax request:

var data = canvas.toDataURL('image/jpg', 1.0);
$.post({
  url: "/upload-image",
  data: { 
    file: data
  }
}).done(function(response) {
  ....
})

}

And on the server side, I want to transmit the image file to an API

function getOptions(buffer) {
  return {
    url: '.../face_detection',
    headers: headers,
    method: 'POST',
    formData: {
      filename: buffer
    }
  }
}

router.post('/upload-image', function(req, res, next) {

  console.log('LOG 0' + Date.now());

  var data_url = req.body.file;
  var matches = data_url.match(/^data:.+\/(.+);base64,(.*)$/);
  var ext = matches[1];
  var base64_data = matches[2];
  var buffer = new Buffer(base64_data, 'base64');

  console.log('LOG 1' + Date.now());

  request(getOptions(buffer), function(error, response, body) {
    res.json(body);
    console.log(Date.now());
  });
});

The problem that I have is that the lines between LOG 0 and LOG 1 are very slow, a few seconds. But the image is only 650kb. Is there a way to accelerate this?

Using another method to read the header, avoid the buffer, change the uploading process. I don't know but I'd like to be faster.

Thank you very much.

Upvotes: 0

Views: 298

Answers (1)

zero298
zero298

Reputation: 26930

I would suggest using a library to handle some of this logic. If you would prefer to keep a lean dependency list, you can take a look at the source of some of these modules and base your own solution off of them.

I would especially recommend the file-type solution. A safer (can't say safest) way to ensure what kind of file a Buffer is is to inspect aspects of the file. file-type seems to at least take a look at the Magic Number of the file to check type. Not foolproof, but if you are accepting files from users, you have to accept the risks involved.

Also have a look at Security Stack Exchange questions for good practices. Although the following say PHP, all server software runs the risk of being vulnerable to user input:


"use strict";

const dataUriToBuffer = require('data-uri-to-buffer'),
    fileType = require("file-type"),
    express = require("express"),
    router = express.Router(),
    util = require("util"),
    fs = require("fs"),
    path = require("path");

const writeFileAsync = util.promisify(fs.writeFile);

// Keep track of file types you support
const supportedTypes = [
    "png",
    "jpg",
    "gif"
];

// Handle POSTs to upload-image
router.post("/upload-image", function (req, res, next) {
    // Did they send us a file?
    if (!req.body.file) {
        // Unprocessable entity error
        return res.sendStatus(422);
    }

    // Get the file to a buffer
    const buff = dataUriToBuffer(req.body.file);

    // Get the file type
    const bufferMime = fileType(buff); // {ext: 'png', mime: 'image/png'}

    // Is it a supported file type?
    if (!supportedTypes.contains(bufferMime.ext)) {
        // Unsupported media type
        return res.sendStatus(415);
    }

    // Save or do whatever with the file
    writeFileAsync(path.join("imageDir", `userimage.${bufferMime.ext}`), buff)
        // Tell the user that it's all done
        .then(() => res.sendStatus(200))
        // Log the error and tell the user the save failed
        .catch((err) => {
            console.error(err);
            res.sendStatus(500);
        });
});

Upvotes: 1

Related Questions