(node.js 模块) 锐利图像处理器保持源文件打开,调整大小后无法取消链接原始文件

Posted

技术标签:

【中文标题】(node.js 模块) 锐利图像处理器保持源文件打开,调整大小后无法取消链接原始文件【英文标题】:(node.js module) sharp image processor keeps source file open, unable to unlink original after resize 【发布时间】:2017-05-08 10:26:30 【问题描述】:

我正在使用sharp 在Node.js / Express 编写的Typescript 应用程序中调整上传图像的大小。成功调整大小后,我想删除原始文件。对于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 是否适用于承诺?可以awaited on 吗? @robertklep 是的,根据文档:sharp.dimens.io/en/stable/api-output toFile() 在没有提供回调时返回一个承诺。 一般来说,在仍然打开的文件上调用unlink 在 Unix 类型的操作系统上不是问题,我假设你正在使用它,因为你使用了正斜杠。如果您使用的是 Windows,请查看 this issue 及其解决方案。 完美!就是这样。将缓存临时设置为 false 解决了该问题。请将此添加为答案,以便我投票+接受。 您使用的是什么版本的夏普?我将 0.17.1 与 Typescript 一起使用,我收到以下错误消息找不到模块“sharp”的声明文件。 '/code/node_modules/sharp/lib/index.js' 隐含了一个 'any' 类型。 (7016) 【参考方案1】:

我最初被您使用正斜杠所困扰,假设您使用的是 Unix 类型的操作系统,在该操作系统中,对仍然打开的文件调用 unlink 通常不成问题。

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

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

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

记录在案的here。

编辑:如某些 cmets 中所述,上面的代码可能无法解决问题。相反,使用这个:

sharp.cache(false);

【讨论】:

一点更正:sharp(...).cache 不是一个函数。我不得不调用 sharp.cache(...) 然后用链式命令分别调用构造函数 sharp(...)。 @AndrásSzepesházi 感谢您的澄清,文档中似乎缺少整个 cache 函数,所以我不得不猜测它是如何工作的。我会更新我的答案:D 不难发现,缓存在实用程序下:sharp.dimens.io/en/stable/api-utility/#cache 只是一个小提示:在 Windows 上,sharp.cache( files : 0 ); 对我不起作用,但 sharp.cache(false); 对我起作用。 @Cosmin Ababi 这里也是。 sharp.cache( files : 0 ); 对我不起作用。【参考方案2】:

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

sharp.cache(false);

在上面添加 REST API 的开头

【讨论】:

以上是关于(node.js 模块) 锐利图像处理器保持源文件打开,调整大小后无法取消链接原始文件的主要内容,如果未能解决你的问题,请参考以下文章

在Node.js中在保持目录结构的情况下压缩指定目录

如何将图像文件从 SVG 转换为多尺寸 ICO 而不模糊(锐利)

如何将 .then() 中的值从 Node.js 模块返回到服务器文件?

我应该将图像存储在MongoDB或本地文件系统中(通过Node.js)

Node.js 使用gm处理图像

Node.js——文件模块和路径模块(读写文件,处理路径)