You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sharp生成缩略图后主文件被占用无法删除问题求助

问题:Sharp生成缩略图后主图片文件被占用无法删除

我在server.js中实现了图片上传功能,使用Sharp生成缩略图,但后续删除主图片文件时失败,报错:
File not accessible: C:\Users\...\uploads\Fan-Art\test-1738586514023.jpg Error: EPERM: operation not permitted, unlink 'C:\Users\...\furwork\uploads\Fan-Art\test-1738586514023.jpg'

手动删除也提示文件被占用,停止server.js后可正常删除;若不生成缩略图则无此问题。

相关端点代码

app.post('/upload-submission', upload.any(), async (req, res) => {
    const folderPath = req.body.folderPath;
    const targetDir = path.join(__dirname, folderPath);
    console.log('Resolved path:', targetDir);
    ...
        // Generate the thumbnail and ensure it finishes before proceeding
        const thumbnailName = `thumb-${path.basename(mainFile.path)}`;
        const thumbnailPath = path.join(targetDir, thumbnailName);

        try {
            // This ensures the Sharp process finishes before continuing
            await sharp(path.join(targetDir, path.basename(mainFile.path)))
                .resize(150, 150)
                .toFile(thumbnailPath);
            console.log("Thumbnail created successfully.");
        } catch (err) {
            console.error('Error creating thumbnail:', err);
            throw new Error('Error creating thumbnail');
        }
        ...
    } catch (err) {
        ...
    }
});

依赖版本

"express": "^4.21.1",
"axios": "^1.7.8",
"sharp": "^0.33.5",
"multer": "^1.4.5-lts.1",

解决方案

这个问题是Windows系统下Sharp未正确释放主图片文件句柄导致的,以下是几种可行修复方式:

1. 先读取文件缓冲区再处理

避免让Sharp直接打开文件路径,改用先读取文件到内存缓冲区,再传给Sharp处理,确保文件句柄被及时释放:

const fs = require('fs/promises');

// 替换原有Sharp处理代码
try {
    const mainFilePath = path.join(targetDir, path.basename(mainFile.path));
    // 读取主文件到缓冲区
    const fileBuffer = await fs.readFile(mainFilePath);
    // 基于缓冲区生成缩略图
    await sharp(fileBuffer)
        .resize(150, 150)
        .toFile(thumbnailPath);
    console.log("Thumbnail created successfully.");
} catch (err) {
    console.error('Error creating thumbnail:', err);
    throw new Error('Error creating thumbnail');
}

2. 显式销毁Sharp实例

虽然await toFile()理论上会完成资源清理,但Windows下可尝试显式销毁Sharp实例,强制释放资源:

try {
    const sharpInstance = sharp(path.join(targetDir, path.basename(mainFile.path)))
        .resize(150, 150);
    await sharpInstance.toFile(thumbnailPath);
    // 显式销毁实例释放资源
    sharpInstance.destroy();
    console.log("Thumbnail created successfully.");
} catch (err) {
    console.error('Error creating thumbnail:', err);
    throw new Error('Error creating thumbnail');
}

3. 验证Multer的文件写入状态

确保Multer已完全完成文件写入操作,可检查mainFile的size属性确认文件已写入完成,或在处理前添加短暂延迟(仅用于排查)。

内容的提问来源于stack exchange,提问作者Zander

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 14:47:11