最近在项目中遇到这样一个需求:上传和下载文件。具体情景以下:php
A上传一份任务文件(文件类型不限)到网站上,B看到后下载文件,按照文件里的要求完成任务以后,B要把任务完成状况汇总到一个Excel文档中,上传到网站上(此时只能上传xls格式的excel文档),而后网站在后台对这份Excel文档的数据进行处理,生成一份新的Excel文档。html
因为该项目是基于Node.js开发,因此,如何实现文件的上传下载功能呢?node
编写form表单页面express
引入formidable,解析表单数据npm
编写业务逻辑函数json
<!DOCTYPE html> <html> <head> <title>node.js实现表单上传与下载文件</title> </head> <body> <form action="/fileupload" method="post" enctype='multipart/form-data' onsubmit="return checkTask(this)"> <label for="resource">上传文档</label> <input type="file" id="resource" name="resource"> <button type="submit">新建任务</button> </form> <a href="download/kkk">下载文件</a> </body> </html>
<form>标签中 enctype="multipart/form-data"
做用是设置表单的MIME编码。
默认状况,这个编码格式是application/x-www-form-urlencoded,不能用于文件上传;只有使用了multipart/form-data,才能完整的传递文件数据。 enctype="multipart/form-data"
是上传二进制数据,form里面的input的值以2进制的方式传过去,因此request就得不到值了。app
所以,咱们要引入node.js的一个外部模块:formidable,对表单数据进行解析。框架
经过npm引入formidable,npm上formidable的描述为:dom
A node.js module for parsing form data, especially file uploads.函数
方式一:经过node命令引入:
npm install formidable
方式二:编辑项目工程里的package.json文件:
{ "name": "appname", "virsion": "0.0.1", "dependencies": { "express": "~4.8.8", "formidable": "1.0.14" } }
执行node命令安装模块
npm install
1.upload函数
新建一个文件:file.js
var formidable = require('formidable'); var fs = require('fs'); //node.js核心的文件处理模块 exports.upload = function(req, res, next){ var message = ''; var form = new formidable.IncomingForm(); //建立上传表单 form.encoding = 'utf-8'; //设置编辑 form.uploadDir = 'public/upload/'; //设置上传目录 form.keepExtensions = true; //保留后缀 form.maxFieldsSize = 2 * 1024 * 1024; //文件大小 form.parse(req, function(err, fields, files) { if (err) { console.log(err); } var filename = files.resource.name; // 对文件名进行处理,以应对上传同名文件的状况 var nameArray = filename.split('.'); var type = nameArray[nameArray.length-1]; var name = ''; for(var i=0; i<nameArray.length-1; i++){ name = name + nameArray[i]; } var rand = Math.random()*100 + 900; var num = parseInt(rand, 10); var avatarName = name + num + '.' + type; var newPath = form.uploadDir + avatarName ; fs.renameSync(files.resource.path, newPath); //重命名 }); };
没有意外的话,文件就上传成功了。
2.download函数
在file.js文件代码末端加入:
exports.download = function(req, res){ var path = 'public/upload/file.txt'; // 文件存储的路径 // filename:设置下载时文件的文件名,可不填,则为原名称 res.download(filepath, filename); };
由于该项目应用了Express(一个基于node.js的Web开发框架),其对request,response对象进行了封装,因此能够直接调用封装好了的res对象的download方法,来下载文件。
接下来,在路由控制文件route.js里加入代码:
var file = require("file.js"); //此时,route.js与file.js处于同个目录下 app.post('/fileupload', file.upload); app.get('/download/:id', file.download); //结合表单页面的<a>标签,里面的kkk是指该文件的id
由于express进行了路由控制,不是像php,asp原生那样请求路径对应于文件路径。除了static资源,其它的请求路径都要配置。因此,在上面针对上传和下载都配置了对应的路由规则。
这样下来,文件的上传和下载功能基本实现,具体的扩展和修改看根据项目具体的需求来调整。