您好,登錄后才能下訂單哦!
這篇文章主要介紹了node.js中express框架怎么實現文件上傳與下載的功能,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
功能實現
前臺部分
前臺使用webUploader插件即可,這是百度開發的一款文件上傳組件,具體使用查看它的API即可。這個項目之前開發的時候前臺使用了angular.js。
$scope.fileName = ""; //創建上傳附件的對象 var $list = $("#thelist"); var uploader = WebUploader.create({ // 選完文件后,是否自動上傳。 auto: false, // swf文件路徑 swf: '../../../lib/webUploader/Uploader.swf', // 文件接收服務端。 server: '/publishUploadFile', // 內部根據當前運行是創建,可能是input元素,也可能是flash. pick : { id : '#filePicker', //只能選擇一個文件上傳 multiple: false }, // pick :'#filePicker', method: 'POST', }); uploader.on('fileQueued', function (file) { $scope.fileName = file.name; $list.html(""); $list.html(file.name); });
當用戶選擇文件的時候我創建了文件上傳的對象,而在用戶真正發送消息的時候我添加了相應的參數并將附件真正的上傳上去,符合我這個項目的業務邏輯。
if($scope.fileName){ //添加參數 uploader.options.formData.fileId = fileId; uploader.options.formData.fileName = $scope.fileName; uploader.upload(); }
后臺部分
路由就不詳細說明了,主要注意的是下載的接口我都是使用的get請求,這樣前臺在請求的時候直接新打開一個窗口拼接了相應的參數就能下載文件了。下面貼一下action層的代碼:
//發布端上傳附件 exports.publishUploadFile = function (req, res) { messageMng.publishUploadFile(req, function (err, datas) { res.json(datas); }); }; //下載發布端上傳的附件 exports.exportPublishFile = function (req, res) { messageMng.exportPublishFile(req, function (err, datas) { if (err) { res.set({ "Content-Disposition": "attachment;filename=" + encodeURI("error.txt") }); res.write(err.message); res.end(); } else { res.download(datas.path, encodeURI(datas.name)); } }); }; //接收端上傳附件 exports.uploadFile = function (req, res) { messageMng.uploadFile(req, function (err, datas) { res.json(datas); }); }; //發布端導出附件 exports.exportFile = function (req, res) { messageMng.exportFile(req, function (err, datas) { if (err) { res.set({ "Content-Disposition": "attachment;filename=" + encodeURI("error.txt") }); res.write(err.message); res.end(); } else { //第一種方式 下載完的zip解壓報錯 // res.download(datas.path, datas.name + ".zip"); //第二種方式 // var path="D:/maven介紹.ppt"; var f = fs.createReadStream(datas.path); res.writeHead(200, { 'Content-Type': 'application/force-download', 'Content-Disposition': 'attachment; filename='+ encodeURI(datas.name) + '.zip' }); f.pipe(res); } }); };
這里著重說一下下載zip時使用download下載完的壓縮包解壓會報錯,使用第二種方法完美解決。
然后是service層的代碼:
/** * 發布端上傳附件 * @param req * @param fn */ MessageManager.prototype.publishUploadFile = function (req, fn) { try { //消息ID var fileId = req.body.fileId; var file = req.file; //文件上傳的目錄 var uploadFolder = path.join(__dirname, '../../upload/publishUploadFile/' + fileId); //判斷文件夾是否存在 不存在則創建 toolUtil.mkdirSync(uploadFolder); //將上傳的文件從臨時目錄拷貝到指定的目錄下 var fileReadStream = fs.createReadStream(file.path); var fileWriteStream = fs.createWriteStream(uploadFolder + "/" + file.originalname); fileReadStream.pipe(fileWriteStream); fileWriteStream.on('close', function () { // 刪除臨時目錄下面的文件 toolUtil.emptyDir(file.destination); }); fn(null, {"data": "", "message": "上傳成功", "error_code": 200}); } catch (e) { fn(e, {"data": "", "message": "上傳失敗", "error_code": e.message}); } }; /** * 下載發布端上傳的附件 * @param req * @param fn */ MessageManager.prototype.exportPublishFile = function (req, fn) { try { //附件ID var id = req.query.id; //附件名稱或標題 var name = req.query.name; if (id && name) { //名稱過長的話,截取前25個字符 if (name.length > 25) { name = name.substr(0, 24); } //將要壓縮得文件夾路徑 var filePath = path.join(__dirname, '../../upload/publishUploadFile/' + id + '/' + name); if (!fs.existsSync(filePath)) { fn(new Error("沒有附件!"), null); } else { fn(null, {"name": name, "path": filePath}); } } else { fn(new Error("id或name不能為空"), null); } } catch (e) { fn(new Error(e.message), null); } }; /** * 接收端上傳附件 * @param req * @param fn */ MessageManager.prototype.uploadFile = function (req, fn) { try { //消息ID var msgId = req.body.msgId; //消息發送的時間 var msgSendTime = req.body.msgSendTime.slice(0, 10); //消息的標題 var title = req.body.title; var replyId = req.body.replyId; var replyName = req.body.replyName; var file = req.file; //文件上傳的目錄 var uploadFolder = path.join(__dirname, '../../upload/messages/' + msgId + '/' + replyName); //判斷文件夾是否存在 不存在則創建 toolUtil.mkdirSync(uploadFolder); //組裝文件的名稱 原名稱+消息發送時間 var index = file.originalname.lastIndexOf("."); var fileName = file.originalname.substr(0, index) + '-' + msgSendTime + ""; var suffix = file.originalname.substr(index, file.originalname.length - 1); //將上傳的文件從臨時目錄拷貝到指定的目錄下 var fileReadStream = fs.createReadStream(file.path); var fileWriteStream = fs.createWriteStream(uploadFolder + "/" + fileName + "." + suffix); fileReadStream.pipe(fileWriteStream); fileWriteStream.on('close', function () { //刪除臨時目錄下面的文件 toolUtil.emptyDir(file.destination); }); fn(null, {"data": "", "message": "上傳成功", "error_code": 200}); } catch (e) { fn(e, {"data": "", "message": "上傳失敗", "error_code": e.message}); } }; /** * 導出消息的附件文件 * @param req * @param fn */ MessageManager.prototype.exportFile = function (req, fn) { try { //消息ID var id = req.query.id; //消息名稱或標題 var name = req.query.name; if (id && name) { //名稱過長的話,截取前25個字符 if (name.length > 25) { name = name.substr(0, 24); } //將要壓縮得文件夾路徑 var messagePath = path.join(__dirname, '../../upload/messages/' + id); if (!fs.existsSync(messagePath)) { fn(new Error("沒有附件!"), null); } else { //生成得臨時zip文件目錄 var zipPath = path.join(__dirname, '../../upload/temp.zip'); var archive = archiver('zip', { // Sets the compression level. zlib: {level: 9} }); //創建臨時zip文件 var output = fs.createWriteStream(zipPath); archive.pipe(output); //設置需要壓縮得文件夾目錄 以及替換得名稱 archive.directory(messagePath, name); archive.finalize(); archive.on('end', function (err) { fn(null, {"name": name, "path": zipPath}); }); archive.on('error', function (err) { fn(new Error("壓縮文件異常"), null); }); } } else { fn(new Error("id或name不能為空"), null); } } catch (e) { fn(new Error(e.message), null); } };
最后是提出的公共方法toolUtil的代碼,這個單獨做為一個js文件維護。
const path = require('path'); const fs = require('fs'); /** * 創建目錄 * @param dirpath */ exports.mkdirSync = function (dirpath){ if (!fs.existsSync(dirpath)) { var pathtmp; dirpath.split(path.sep).forEach(function(dirname) { if (pathtmp) { pathtmp = path.join(pathtmp, dirname); } else { pathtmp = dirname; } if (!fs.existsSync(pathtmp)) { fs.mkdirSync(pathtmp); } }); } }; //刪除所有的文件(將所有文件夾置空) exports.emptyDir = function(dirpath){ var self = this; //讀取該文件夾 var files = fs.readdirSync(dirpath); files.forEach(function(file){ var filePath = dirpath + '/' + file; var stats = fs.statSync(filePath); if(stats.isDirectory()){ self.emptyDir(filePath); }else{ fs.unlinkSync(filePath); } }); };
感謝你能夠認真閱讀完這篇文章,希望小編分享的“node.js中express框架怎么實現文件上傳與下載的功能”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。