(node.js模块) sharp图像处理器保持源文件打开,在调整大小后无法删除原始文件

15

我正在使用sharp在一个使用Typescript编写的Node.js/Express应用程序中调整上传的图像大小。成功调整大小后,我想删除原始文件。对于pnggif输入图像,操作成功终止,我有调整大小的图像,并且原始图像已被删除。对于jpgtif图像,调整大小是成功的,但是unlink命令失败,并显示以下错误:

EBUSY: 资源正忙或已锁定,无法删除“...”

就好像sharp().resize()仍然保持着输入文件的锁定状态,即使在调整大小操作完成后也是如此。

这里是测试所述行为的代码:

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));
}

我漏掉了什么?


sharp 能够与 Promises 一起使用吗? 它可以被 await 吗? - robertklep
@robertklep 是的,根据文档:http://sharp.dimens.io/en/stable/api-output/ 当没有提供回调函数时,toFile() 返回一个 Promise。 - András Szepesházi
通常,在 Unix 类型的操作系统上调用 unlink 删除一个仍然打开的文件不是问题,我假设你正在使用这种操作系统,因为你使用了正斜杠。如果你在 Windows 上,请查看 此问题 及其解决方案。 - robertklep
太好了!就是这样。将缓存暂时设置为false解决了问题。请将此作为答案添加,以便我可以点赞和接受它。 - András Szepesházi
你使用的是哪个版本的sharp?我正在使用带有TypeScript的0.17.1版本,但我收到了以下错误信息:“无法找到模块'sharp'的声明文件。'/code/node_modules/sharp/lib/index.js'隐式具有“any”类型。(7016)” - hpelleti
2个回答

16

一开始我对你使用斜线感到困惑,认为你会使用类Unix操作系统,在这种操作系统中调用 unlink 删除一个仍然打开的文件通常不是问题。

但是,在Windows上,我认为打开的文件通常会受到保护以防止被删除,此问题描述了一个类似的问题,并提供了解决方案:内部,sharp 维护一个缓存(打开)文件,这将阻止原始文件被删除。

如果你禁用该缓存,则问题应该得到解决:

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

这里记录了相关信息。

编辑:正如某些评论中指出的那样,上面的代码可能无法解决问题。相反,请使用以下代码:

sharp.cache(false);

1
稍作更正:sharp(...).cache不是一个函数。我必须调用sharp.cache(...),然后再使用链接命令单独调用构造函数sharp(...)。 - András Szepesházi
1
@AndrásSzepesházi 感谢您的澄清,整个“cache”函数似乎在文档中都没有提到,所以我只能猜测它的工作方式。我会更新我的答案:D - robertklep
6
只是一个小提示:在Windows上,sharp.cache({ files : 0 }); 对我无效,但是 sharp.cache(false); 可以。 - Cosmin Ababei
1
@Cosmin Ababi 我也是。sharp.cache({ files : 0 }); 对我也没用。 - Jeff
这个答案已经出现了链接失效的情况。 - Luke
显示剩余3条评论

3

在内部,Sharp 维护一个(打开的)文件缓存,这会阻止原始文件被删除。

sharp.cache(false);

以上代码行添加到你的 REST API 的开头。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接