Reach filesize limit,egg-multipart上传失败以后,临时文件无法删除,会导致服务器占用存储空间越来越大
litteredxiao opened this issue · comments
在此输入你需要反馈的 Bug 具体信息(Bug in Detail):
通过egg-multipart上传的文件超过默认配置的大小限制,会抛出异常,但是无法删除上传失败的临时文件,上传的临时文件就是egg-mulipart配置的filesize大小,最终会导致服务器存储空间占满
上传文件抛出异常以后,catch中捕获的异常requestFiles
是空数组
可复现问题的仓库地址(Reproduction Repo)
async saveRequestFiles(options = {}) {
const ctx = this;
const allowArrayField = ctx.app.config.multipart.allowArrayField;
let storedir;
const requestBody = {};
const requestFiles = [];
options.autoFields = false;
const parts = ctx.multipart(options);
try {
for await (const part of parts) {
if (Array.isArray(part)) {
// fields
const [ fieldName, fieldValue ] = part;
if (!allowArrayField) {
requestBody[fieldName] = fieldValue;
} else {
if (!requestBody[fieldName]) {
requestBody[fieldName] = fieldValue;
} else if (!Array.isArray(requestBody[fieldName])) {
requestBody[fieldName] = [ requestBody[fieldName], fieldValue ];
} else {
requestBody[fieldName].push(fieldValue);
}
}
} else {
// stream
const { filename, fieldname, encoding, mime } = part;
if (!storedir) {
// ${tmpdir}/YYYY/MM/DD/HH
storedir = path.join(ctx.app.config.multipart.tmpdir, dayjs().format('YYYY/MM/DD/HH'));
await fs.mkdir(storedir, { recursive: true });
}
// write to tmp file
const filepath = path.join(storedir, randomUUID() + path.extname(filename));
const target = createWriteStream(filepath);
await pipeline(part, target);
const meta = {
filepath,
field: fieldname,
filename,
encoding,
mime,
// keep same property name as file stream, https://github.com/cojs/busboy/blob/master/index.js#L114
fieldname,
transferEncoding: encoding,
mimeType: mime,
};
requestFiles.push(meta);
}
}
} catch (err) {
await ctx.cleanupRequestFiles(requestFiles);
throw err;
}
ctx.request.body = requestBody;
ctx.request.files = requestFiles;
},
Node 版本号:
v14.21.3
Eggjs 版本号:
3.3.3
相关插件名称与版本号(PlugIn and Name):
egg-multipart 3.3.0
操作平台与版本号(Platform and Version):
linux
https://www.eggjs.org/zh-CN/basics/controller#%E8%8E%B7%E5%8F%96%E4%B8%8A%E4%BC%A0%E7%9A%84%E6%96%87%E4%BB%B6 建议你改成 File 模式,Stream 模式需要做很多处理才能做好这件事情。
你上面贴的代码明显就是没有处理好各种异常边界条件,导致临时文件没有处理。
@fengmk2
上面贴的代码并非业务代码,而是egg-multipart插件中的源码
源码中的await pipeline(part, target);
这一行代码报错,触发了catch以后无法删除临时文件,因为原本定义的requestFiles.push(meta);
这行代码无法执行,requestFiles这个数组是空数组
我们原有的使用方式就是file模式