最近在項目中遇到這樣一個需求:上傳和下載文件。具體情景以下: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資源,其它的請求路徑都要配置。因此,在上面針對上傳和下載都配置了對應的路由規則。
這樣下來,文件的上傳和下載功能基本實現,具體的擴展和修改看根據項目具體的需求來調整。