最近用koa重写express项目,其中有上传文件的模块,需要用到koa-formidable,在这里做一下记录.
首先是express下formidable模块上传文件
function upfile(req, res) {
var fs = require('fs');
var http = require('http');
var formidable = require('formidable');
var body = '';
//req 是一个路由里面的请求
var form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
var file = files.file; // 这里的file是前端命名的
var filename = file.name;
var buffer = fs.readFileSync(file.path); // 读取文件,此时就可以上传了
//...其他的加密,md5,文件大小等等
//用http模块上传到指定服务器
var opts = {
hostname: hostname,
port: port,
path: url,
method: post,
headers: {
'Content-Length': buffer.length,
'Connection': 'Keep-Alive',
//...其他一些参数
}
}
http.request(opts, function (resp) {
resp.setEncoding('utf8');
resp.on('data', function (chunk) {
body += chunk; // 这个是上传的服务器返回的结果
})
resp.on('end', function () {
try {
var result = JSON.parse(body);
return res.send(result); //上传结束客户端返回
} catch (e) {
return res.send(e);
}
})
}).on('error',function(e){
return res.send(e); //出错后返回
}).write(buffer) // http上次
.end();
})
}
express里面用法比较直接form.parse(req,callback) 回调函数就可以获取到上传的文件信息,在koa2里面路由下的函数是异步的,也没有回调函数,用的是async/await
// 这个是一个异步,在路由里面前面是有async的
const upkoafile = async (ctx, next) => {
var fs = require('fs');
var formidable = require('koa-formidable'); // 这里用koa下的formidable模块,如果直接套用会出现关于req.on 的报错
// 直接new formidable.IncomingForm() 也会报错它不能new,或者说下面这句已经帮我们new好了
var form = formidable.parse(ctx.request);
/*
这里的form是一个函数,具体如下
function (done) {
var form = opts instanceof formidable.IncomingForm
? opts
: new formidable.IncomingForm(opts)
form.parse(ctx.req, function (err, fields, files) {
if (err) return done(err)
done(null, { fields: fields, files: files })
})
}
看到这里,我想有人应该明白了,koa-formidable只不过在原来的模块基础上加了一点东西,甚至可以不用这个模块
var formidable = require('formidable');
var form = new formidable.IncomingForm();
form.parse(ctx.req,function(){...})
*/
var p = new Promise((resolve, reject) => {
form((opt, obj) => {
var file = obj.files.file;
var filename = file.name;
var buffer = fs.readFileSync(file.path); // 读取文件,此时就可以上传了
//... 到这里就已经回到之前的步骤了,后面的http只需要在合适的地方返回promise就行了
var opts = {
//...上面一样
}
http.request(opts, function (resp) {
resp.setEncoding('utf8');
resp.on('data', function (chunk) {
body += chunk; // 这个是上传的服务器返回的结果
})
resp.on('end', function () {
try {
var result = JSON.parse(body);
return resolve(result); //上传结束客户端返回
} catch (e) {
return reject(e);
}
})
}).on('error', function (e) {
return reject(e); //出错后返回
}).write(buffer) // http上次
.end();
})
})
var body = await p; //上面的promise返回
return ctx.body = body;
}
在koa异步函数中,回调函数中返回会出问题的,也就是return ctx.body这句需要用await接收返回结果,如果在回调函数里面,那koa会直接返回404,并且可能造成其他的错误,比如throw new Error('Can\'t set headers after they are sent.');
在koa2里面对于async/await使用要注意同步返回结果.