需求
最近在项目中遇到这样一个需求:上传和下载文件。具体情景如下:
A上传一份任务文件(文件类型不限)到网站上,B看到后下载文件,按照文件里的要求完成任务之后,B要把任务完成情况汇总到一个Excel文档中,上传到网站上(此时只能上传xls格式的excel文档),然后网站在后台对这份Excel文档的数据进行处理,生成一份新的Excel文档。
由于该项目是基于Node.js开发,所以,如何实现文件的上传下载功能呢?
实现
思路
编写form表单页面
引入formidable,解析表单数据
编写业务逻辑函数
编写form表单页面
<!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就得不到值了。
因此,我们要引入node.js的一个外部模块:formidable,对表单数据进行解析。
引入formidable,解析表单数据
通过npm引入formidable,npm上formidable的描述为:
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资源,其它的请求路径都要配置。所以,在上面针对上传和下载都配置了对应的路由规则。
这样下来,文件的上传和下载功能基本实现,具体的扩展和修改看根据项目具体的需求来调整。