本文转自http://itbilu.com/nodejs/npm/NkGKcF14.html
在web开发中,经常遇到处理文件上传的情况。而express框架在4.0版本后就不在支持req.files接收上传文件,对于文件上传,需要加multipart格式数据处理的中间件。multipart数据处理中间件有:busboy, multer, formidable, multiparty, connect-multiparty, pez等。本站使用了formidable插件,比较简单易用。
formidable是一个用于处理文件、图片、视频等数据上传的模块,支持GB级上传数据处理,支持多种客户端数据提交。有极高的测试覆盖率,非常适合在生产环境中使用。
安装
formidable是一个轻量级的应用包,可以不依赖于express等框架单独使用,也可以集成到exress框架中使用。安装命令如下:
- npm install formidable@latest
使用
在nodejs原生环境中使用formidable。
- var formidable = require('formidable'),
- http = require('http'),
- util = require('util');
- //用http模块创建一个http服务端
- http.createServer(function(req, res) {
- if (req.url == '/upload' && req.method.toLowerCase() === 'post') {
- // 处理上传的文件
- var form = new formidable.IncomingForm();
- form.parse(req, function(err, fields, files) {
- res.writeHead(200, {'content-type': 'text/plain'});
- res.write('received upload:\n\n');
- res.end(util.inspect({fields: fields, files: files}));
- });
- return;
- }
上传后,响应结果如下
- received upload:
- { fields: { title: 'title的内容' },
- files: //所有type="file"类型的数据对象
- { upload:
- { domain: null,
- _events: {},
- _maxListeners: 10,
- size: 41966, //文件大小
- path: '/var/folders/1k/86kq55_n4_q2tckwz9mb5wyr0000gn/T/upload_ecbf965abc1e14c2ffc86875c2f5eaa8', //文件保存路径
- name: 'avatar.jpg', //上传前的文件名
- type: 'image/jpeg', //文件类型
- hash: null,
- lastModifiedDate: Sat May 16 2015 10:38:57 GMT+0800 (CST),
- _writeStream: [Object] } } }
常用API
创建一个incoming form实例- var form = new formidable.IncomingForm()
设置incoming form fields(fileds指除type="file"外的其它接收数据)编码
- form.encoding = 'utf-8';
设置文件接收后保存的文件夹。此文件夹一般为上传后的临时文件夹,上传后调用 fs.rename()对文件进行移动及重命名。默认保存路径为os.tmpDir()
- form.uploadDir = "/my/dir";
- form.keepExtensions = false;
'multipart'或'urlencoded'类型的请求在formidable都支持,可通过上传文件的type属性查看文件类型
- form.type
- form.maxFieldsSize = 2 * 1024 * 1024;
- form.maxFields = 1000;
- form.hash = false;
在express中使用formidable
在express框架中使用formidable,需要一个接收文件提交的路由。以下示例为一个接收用户头像提交的路由- router.post("/user/avatar", user.avatar);
路由对应的接收提交数据的方法
- //设置头像
- exports.avatar = function(req, res, next) {
- var form = new formidable.IncomingForm();
- form.uploadDir = path.join(__dirname, 'tmp'); //文件保存的临时目录为当前项目下的tmp文件夹
- form.maxFieldsSize = 1 * 1024 * 1024; //用户头像大小限制为最大1M
- form.keepExtensions = true; //使用文件的原扩展名
- form.parse(req, function (err, fields, file) {
- var filePath = '';
- //如果提交文件的form中将上传文件的input名设置为tmpFile,就从tmpFile中取上传文件。否则取for in循环第一个上传的文件。
- if(file.tmpFile){
- filePath = file.tmpFile.path;
- } else {
- for(var key in file){
- if( file[key].path && filePath==='' ){
- filePath = file[key].path;
- break;
- }
- }
- }
- //文件移动的目录文件夹,不存在时创建目标文件夹
- var targetDir = path.join(__dirname, 'upload');
- if (!fs.existsSync(targetDir)) {
- fs.mkdir(targetDir);
- }
- var fileExt = filePath.substring(filePath.lastIndexOf('.'));
- //判断文件类型是否允许上传
- if (('.jpg.jpeg.png.gif').indexOf(fileExt.toLowerCase()) === -1) {
- var err = new Error('此文件类型不允许上传');
- res.json({code:-1, message:'此文件类型不允许上传'});
- } else {
- //以当前时间戳对上传文件进行重命名
- var fileName = new Date().getTime() + fileExt;
- var targetFile = path.join(targetDir, fileName);
- //移动文件
- fs.rename(filePath, targetFile, function (err) {
- if (err) {
- console.info(err);
- res.json({code:-1, message:'操作失败'});
- } else {
- //上传成功,返回文件的相对路径
- var fileUrl = '/upload/' + fileName;
- res.json({code:0, fileUrl:fileUrl});
- }
- });
- }
- });
- }