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
相关产品推荐
相关产品推荐

