busboy模块
模块是用来解析POST请求,node原生req中的文件流。
busboy 是用来解析出请求中文件流。
封装上传文件到写入服务的方法
创建上传模块upload.js
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
const inspect = require('util').inspect;const path = require('path');const os = require('os');const fs = require('fs');const Busboy = require('busboy');/** 同步创建文件目录* @param {string} dirname 目录绝对地址* @return {boolean} 创建目录结果*/function mkdirsSync (dirname) { if (fs.existsSync(dirname)) { return true; } else { if (mkdirsSync(path.dirname(dirname))) { fs.mkdirSync(dirname); return true; } }}/** 获取上传文件的后缀名* @param {string} fileName 获取上传文件的后缀名* @return {string} 文件后缀名*/function getSuffixName (fileName) { /*let nameList = fileName.split('.'); return nameList[nameList.length-1]*/ return path.extname(fileName);}/** 上传文件* @param {object} ctx koa上下文* @param {object} options 文件上传参数 fileType文件类型, path文件存放路径* @return {promise}*/function uploadFile (ctx, options) { let req = ctx.req; let res = ctx.res; let busboy = new Busboy({headers: req.headers}); // 获取类型 let fileType = options.fileType || 'common'; let filePath = path.join(options.path, fileType); let mkdirResult = mkdirsSync(filePath); return new Promise((resolve, reject) => { console.log('文件上传中...'); let result = { success: false, formData: {}, }; // 解析请求文件事件 busboy.on('file', function(fieldname, file, filename, encoding, mimetype) { let fileName = Math.random().toString(16).substr(2) + '.' + getSuffixName(filename) let _uploadFilePath = path.join( filePath, fileName ) let saveTo = path.join(_uploadFilePath) // 文件保存到制定路径 file.pipe(fs.createWriteStream(saveTo)) // 文件写入事件结束 file.on('end', function() { result.success = true result.message = '文件上传成功' console.log('文件上传成功!') resolve(result) }) }) // 解析表单中其他字段信息 busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) { console.log('表单字段数据 [' + fieldname + ']: value: ' + inspect(val)); result.formData[fieldname] = inspect(val); }); // 解析结束事件 busboy.on('finish', function( ) { console.log('文件上结束') resolve(result) }) // 解析错误事件 busboy.on('error', function(err) { console.log('文件上出错') reject(result) }) req.pipe(busboy) });}module.exports = { uploadFile}
入口文件
123456789101112131415161718192021222324252627282930313233343536373839404142434445
const Koa = require('koa')const path = require('path')const app = new Koa()// const bodyParser = require('koa-bodyparser')const { uploadFile } = require('./util/upload')// app.use(bodyParser())app.use( async ( ctx ) => { if ( ctx.url === '/' && ctx.method === 'GET' ) { // 当GET请求时候返回表单页面 let html = ` <h1>koa2 upload demo</h1> <form method="POST" action="/upload.json" enctype="multipart/form-data"> <p>file upload</p> <span>picName:</span><input name="picName" type="text" /><br/> <input name="file" type="file" /><br/><br/> <button type="submit">submit</button> </form> ` ctx.body = html } else if ( ctx.url === '/upload.json' && ctx.method === 'POST' ) { // 上传文件请求处理 let result = { success: false } let serverFilePath = path.join( __dirname, 'upload-files' ) // 上传文件事件 result = await uploadFile( ctx, { fileType: 'album', // common or album path: serverFilePath }) ctx.body = result } else { // 其他请求显示404 ctx.body = '<h1>404!!! o(╯□╰)o</h1>' }})app.listen(3004, () => { console.log('[demo] upload-simple is starting at port 3000')})