问题现象:批量上传文件时会出现某几个文件始终处于上传状态,对应的上传请求处于挂起状态。 BUG排查:
// node_modules/egg-multipart/app/extend/context.js
async saveRequestFiles(options) {
options = options || {};
const ctx = this;
const multipartOptions = {
autoFields: false,
};
if (options.defCharset) multipartOptions.defCharset = options.defCharset;
if (options.limits) multipartOptions.limits = options.limits;
if (options.checkFile) multipartOptions.checkFile = options.checkFile;
let storedir;
const requestBody = {};
const requestFiles = [];
const parts = ctx.multipart(multipartOptions);
let part;
do {
try {
part = await parts();
} catch (err) {
await ctx.cleanupRequestFiles(requestFiles);
throw err;
}
if (!part) break;
if (part.length) {
ctx.coreLogger.debug('[egg-multipart:storeMultipart] handle value part: %j', part);
const fieldnameTruncated = part[2];
const valueTruncated = part[3];
if (valueTruncated) {
await ctx.cleanupRequestFiles(requestFiles);
limit('Request_fieldSize_limit', 'Reach fieldSize limit');
}
if (fieldnameTruncated) {
await ctx.cleanupRequestFiles(requestFiles);
limit('Request_fieldNameSize_limit', 'Reach fieldNameSize limit');
}
// arrays are busboy fields
requestBody[part[0]] = part[1];
continue;
}
// otherwise, it's a stream
const meta = {
field: part.fieldname,
filename: part.filename,
encoding: part.encoding,
mime: part.mime,
};
// keep same property name as file stream
// https://github.com/cojs/busboy/blob/master/index.js#L114
meta.fieldname = meta.field;
meta.transferEncoding = meta.encoding;
meta.mimeType = meta.mime;
ctx.coreLogger.debug('[egg-multipart:storeMultipart] handle stream part: %j', meta);
// empty part, ignore it
if (!part.filename) {
await sendToWormhole(part);
continue;
}
if (!storedir) {
// ${tmpdir}/YYYY/MM/DD/HH
storedir = path.join(ctx.app.config.multipart.tmpdir, moment().format('YYYY/MM/DD/HH'));
const exists = await fs.exists(storedir);
if (!exists) {
await mkdirp(storedir);
}
}
const filepath = path.join(storedir, uuid.v4() + path.extname(meta.filename));
const target = fs.createWriteStream(filepath);
await pump(part, target);
// https://github.com/mscdex/busboy/blob/master/lib/types/multipart.js#L221
meta.filepath = filepath;
requestFiles.push(meta);
// https://github.com/mscdex/busboy/blob/master/lib/types/multipart.js#L221
if (part.truncated) {
await ctx.cleanupRequestFiles(requestFiles);
limit('Request_fileSize_limit', 'Reach fileSize limit');
}
} while (part != null);
ctx.request.body = requestBody;
ctx.request.files = requestFiles;
},
导致该问题的原因是egg-multipart的saveRequestFiles()没有生成对应的part文件。