一、获取单文件上传的流数据
const stream = await ctx.getFileStream(); // get upload file stream
二、获取多文件上传的流数据
// 多文件上传
// 获取前台多文件
// 创建多段实例以获取指定的文件
// 处理完成后必须将上传的文件流消费掉,不然不会http响应请求
const sendToWormhole = require('stream-wormhole');
const fnPart = ctx.multipart(); // 返回一个函数(函数返回promise)
let part;
// 每个part代表一个FileStream,循环获取上传的文件,直到part为空
while (part = await fnPart()) {
const { filename, fieldname } = part;
try {
// ***
// 执行业务逻辑
// ***
} catch(error) {
// 如果可读流在处理期间发送错误,则可写流目标不会自动关闭。 如果发生错误,则需要手动关闭每个流以防止内存泄漏。
//必须将上传的文件流消费掉,不然不会http响应请求
await sendToWormhole(part);
}
}
/* FileStream 数据结构
FileStream {
_readableState: ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: BufferList { head: [Object], tail: [Object], length: 1 }, // 文件buffer
length: 64990,
pipes: null,
pipesCount: 0,
flowing: null,
ended: false,
endEmitted: false,
reading: false,
sync: true,
needReadable: false,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
emitClose: true,
autoDestroy: false,
destroyed: false,
defaultEncoding: 'utf8',
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null,
[Symbol(kPaused)]: null
},
readable: true,
_events: [Object: null prototype] { end: [Function] },
_eventsCount: 1,
_maxListeners: undefined,
truncated: false,
_read: [Function],
fieldname: 'bak', // 请求参数的key
filename: 'bak_hunan_psql_public.png', // 请求参数的value
encoding: '7bit',
transferEncoding: '7bit',
mime: 'image/png',
mimeType: 'image/png',
[Symbol(kCapture)]: false
}
*/
三、以流数据形式响应请求
//后台:响应http请求,以流的形式
//前台:请求成功后直接加载图片
//ctx.response.res 等同于 ctx.res
//两种方式
//1、
new stream.PassThrough().end(bufferData).pipe(ctx.res);
// 2、
const Duplex = stream.Duplex;
const streamData = new Duplex();
streamData.push(bufferData);
streamData.push(null);
streamData.pipe(ctx.response.res);
四、拓展
egg-multipart多段上传 通过流处理,无须保存到磁盘