Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(node.js module) sharp image processor keeps source file open, unable to unlink original after resize

I'm using sharp to resize an uploaded image in a Node.js / Express application written in Typescript. After successful resizing, I'd like to delete the original file. For png and gif input images, the operation terminates successfully, I have the resized image and the original is deleted. For jpg and tif images, the resize is successful, however the unlink command fails with the following error:

EBUSY: resource busy or locked, unlink '...'

as if the sharp().resize() would still keep the input file locked, even after the completion of the resize operation.

Here is the code to test the described behavior:

import { existsSync, unlinkSync } from "fs";
import { normalize, parse } from "path";

var argv = require("yargs").argv;
var sharp = require("sharp");
var appRoot = require("app-root-path") + "/";

let resizeTest = async function (filename: string): Promise<boolean> {
    try {
        let nameParts = parse(filename);
        let source = appRoot + filename;
        let destination = appRoot + nameParts.name + "_resized" + nameParts.ext;
        let fileExists = await existsSync(source);
        if (!fileExists) {
            console.log("Input file not found. Exiting.");
            return false;
        }

        let resizeResult = await sharp(source)
            .resize(128, 128)
            .toFile(destination);
        console.log("Resize operation terminated: ", resizeResult);

        await unlinkSync(source);
        console.log("unlinkSync operation terminated.");

        return true;
    } catch (error) {
        console.log("An error occured during resizeTest execution: ", error.message);
        return false;
    }
}

if (argv._.length === 0) {
    console.log("Usage: node sharptest.js FILENAME");
} else {
    let resizeResult: Promise<boolean> = resizeTest(argv._[0]);
    resizeResult.then(result => console.log("Returning from execution with ", result));
}

What am I missing?

like image 743
András Szepesházi Avatar asked Dec 22 '16 17:12

András Szepesházi


People also ask

How do I resize an image in node JS?

NodeJS – Resize() is an inbuilt function that is used to resize the images to the desired size. We can use resize to set the height and width using a 2-pass bilinear algorithm. It can resize an image into any size as declared by the user. We can take input from the user or resize it into fixed Width*Height size.

Is Node JS good for image processing?

With image processing, your application can resize and compress all the user-uploaded images, which can significantly improve your application performance and save your server disk space. Node. js has an ecosystem of libraries you can use to process images, such as sharp, jimp, and gm module.


1 Answers

I initially was thrown by your use of forward slashes, assuming that you'd be using a Unix-type OS, where calling unlink of a file that is still open generally isn't a problem.

However, on Windows, I think that open files are usually protected from being deleted, and this issue describes a similar problem, and also a solution: internally, sharp maintains a cache of (open) files, which will block the original file from being deleted.

If you disable that cache, the problem should be fixed:

// add this at the top of your code
sharp.cache({ files : 0 });

Documented here.

EDIT: as noted in some of the comments, the code above may not fix the problem. Instead, use this:

sharp.cache(false);
like image 64
robertklep Avatar answered Sep 21 '22 11:09

robertklep