Sumit Aggarwal Sumit Aggarwal - 3 months ago 50x
Javascript Question

How to crop and upload image in ejs and Node.JS?

I'm using JQuery to crop an image.

<link href="/public/css/jquery.Jcrop.min.css" rel="stylesheet" type="text/css" />

<!-- add scripts -->
<script src=""></script>
<script src=""></script>
<script src="/public/js/jquery.Jcrop.min.js"></script>
<script src="/public/js/script.js"></script>

<form id="upload_form" enctype="multipart/form-data" method="post" action="upload.php" onsubmit="return checkForm()">
<!-- hidden crop params -->
<input type="hidden" id="x1" name="x1" />
<input type="hidden" id="y1" name="y1" />
<input type="hidden" id="x2" name="x2" />
<input type="hidden" id="y2" name="y2" />

<h2>Step1: Please select image file</h2>
<div><input type="file" name="image_file" id="image_file" onchange="fileSelectHandler()" /></div>

<div class="error"></div>

<div class="step2">
<h2>Step2: Please select a crop region</h2>
<img id="preview" />

<div class="info">
<label>File size</label> <input type="text" id="filesize" name="filesize" />
<label>Type</label> <input type="text" id="filetype" name="filetype" />
<label>Image dimension</label> <input type="text" id="filedim" name="filedim" />
<label>W</label> <input type="text" id="w" name="w" />
<label>H</label> <input type="text" id="h" name="h" />

<input type="submit" value="Upload" onclick="return checkForm()"/>

For the above code I have an x, y co-ordinations, width and height of
crop image and in the backend I am using the multer module in Node.JS. In
that I don't know how can I pass x and y coordinates to that multer
code. In my main file app.js I declare the module like

var FormData = require('form-data');
var multer = require('multer');
var upload = multer({ dest: 'uploads/' });

and in the controller i used like this'/profile', BASE.upload.single('avatar'), function (req, res, next) {
// req.file is the `avatar` file
// req.body will hold the text fields, if there were any


BASE.FS.readFile(req.file.path, function read(err, data) {
if (err) {
throw err;

In this way the file is uploaded but not the cropped one.


This should do what you want it to. I like to use sharp for image manipulation. Scrap that, saw you needed to crop and not resize! Use gm for this.

(EDIT: Lovell pointed out in the comments that sharp can be used - "sharp supports region extraction, similar to the crop feature, of gm, via its extract operation". See his comment for more info.)

HTML for getting form image size:

<form method="post" action="/">
    <input type="hidden" id="x1" name="x1" />
    <input type="hidden" id="y1" name="y1" />
    <input type="hidden" id="x2" name="x2" />
    <input type="hidden" id="y2" name="y2" />
    <input type="submit" value="Submit">


var FormData = require('form-data');
var qs = require('querystring');
var multer  = require('multer');
var gm = require('gm');

function (request, response) {
  if (request.method == 'POST') {
    let body = '';

    request.on('data', function (data) {
      body += data;

      // Too much POST data, kill the connection!
      // 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
      if (body.length > 1e6) request.connection.destroy();

    request.on('end', function () {
      // The POST variables are now within the `var post`
      const post = qs.parse(body);
      const x1 = post["x1"];
      const x2 = post["x2"];
      const y1 = post["y1"];
      const y2 = post["y2"];

      let upload = multer({
        dest: 'uploads/'
      });'/profile', BASE.upload.single('avatar'), function(req, res, next) {
        const imagePath = req.file.path;
        const imageOutputPath = "/some/other/path";

          .crop(x1, y1, x2, y2)
          .write(imageOutputPath, function (err) {
            if (!err) console.log('done');

While this does what you've asked, also consider user input errors, such as specifying too large of a crop area for a particular image (e.g., trying to crop a 200px square region from a 50px square image - that's not possible). I'll leave that to you!