亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

node.js express框架實現(xiàn)文件上傳與下載功能實例詳解

 更新時間:2019年10月15日 11:01:05   作者:機智的導演  
這篇文章主要介紹了node.js express框架實現(xiàn)文件上傳與下載功能,結合具體實例形式詳細分析了node.js express框架針對文件上傳與下載的前后臺相關實現(xiàn)技巧,需要的朋友可以參考下

本文實例講述了node.js express框架實現(xiàn)文件上傳與下載功能。分享給大家供大家參考,具體如下:

背景

昨天吉視傳媒的客戶對IPS信息發(fā)布系統(tǒng)又提了一個新需求,就是發(fā)布端發(fā)送消息時需要支持附件的上傳,而接收端可以對發(fā)布端上傳的附件進行下載;接收端回復消息時也需要支持上傳附件,發(fā)布端可以對所有接收端上傳的附件進行打包下載。

功能實現(xiàn)

  • 前臺部分

前臺使用webUploader插件即可,這是百度開發(fā)的一款文件上傳組件,具體使用查看它的API即可。這個項目之前開發(fā)的時候前臺使用了angular.js。

  $scope.fileName = "";
  //創(chuàng)建上傳附件的對象
  var $list = $("#thelist");
  var uploader = WebUploader.create({
    // 選完文件后,是否自動上傳。
    auto: false,
    // swf文件路徑
    swf: '../../../lib/webUploader/Uploader.swf',
    // 文件接收服務端。
    server: '/publishUploadFile',
    // 內部根據(jù)當前運行是創(chuàng)建,可能是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);
  });

當用戶選擇文件的時候我創(chuàng)建了文件上傳的對象,而在用戶真正發(fā)送消息的時候我添加了相應的參數(shù)并將附件真正的上傳上去,符合我這個項目的業(yè)務邏輯。

if($scope.fileName){
  //添加參數(shù)
  uploader.options.formData.fileId = fileId;
  uploader.options.formData.fileName = $scope.fileName;
  uploader.upload();
}

  • 后臺部分

路由就不詳細說明了,主要注意的是下載的接口我都是使用的get請求,這樣前臺在請求的時候直接新打開一個窗口拼接了相應的參數(shù)就能下載文件了。下面貼一下action層的代碼:

//發(fā)布端上傳附件
exports.publishUploadFile = function (req, res) {
  messageMng.publishUploadFile(req, function (err, datas) {
    res.json(datas);
  });
};
//下載發(fā)布端上傳的附件
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);
  });
};
//發(fā)布端導出附件
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層的代碼:

/**
 * 發(fā)布端上傳附件
 * @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);
    //判斷文件夾是否存在 不存在則創(chuàng)建
    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});
  }
};
/**
 * 下載發(fā)布端上傳的附件
 * @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;
    //消息發(fā)送的時間
    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);
    //判斷文件夾是否存在 不存在則創(chuàng)建
    toolUtil.mkdirSync(uploadFolder);
    //組裝文件的名稱 原名稱+消息發(fā)送時間
    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}
        });
        //創(chuàng)建臨時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');
/**
 * 創(chuàng)建目錄
 * @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程序設計有所幫助。

相關文章

  • 詳解離線安裝npm包的幾種方法

    詳解離線安裝npm包的幾種方法

    這篇文章主要介紹了詳解離線安裝npm包的幾種方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11
  • 搭建一個Koa后端項目腳手架的方法步驟

    搭建一個Koa后端項目腳手架的方法步驟

    這篇文章主要介紹了搭建一個Koa后端項目腳手架的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-05-05
  • 前端面試之輸入npm?run后執(zhí)行原理

    前端面試之輸入npm?run后執(zhí)行原理

    這篇文章主要為大家介紹了前端面試之輸入npm?run后發(fā)生了什么及執(zhí)行原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • nodejs的http和https下載遠程資源post數(shù)據(jù)實例

    nodejs的http和https下載遠程資源post數(shù)據(jù)實例

    這篇文章主要為大家介紹了nodejs的http和https下載遠程資源post數(shù)據(jù)實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • node實現(xiàn)mock-plugin中間件的方法

    node實現(xiàn)mock-plugin中間件的方法

    這篇文章主要介紹了node實現(xiàn)mock-plugin中間件的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-12-12
  • Node 創(chuàng)建第一個服務器應用的操作方法

    Node 創(chuàng)建第一個服務器應用的操作方法

    Node.js是一個基于Chrome V8引擎的JavaScript運行環(huán)境,可以用于構建高性能的網(wǎng)絡應用程序,它采用事件驅動、非阻塞I/O模型,使得程序可以以高效地方式處理并發(fā)請求,這篇文章主要介紹了Node 創(chuàng)建第一個服務器應用,需要的朋友可以參考下
    2024-02-02
  • node.js中的fs.futimes方法使用說明

    node.js中的fs.futimes方法使用說明

    這篇文章主要介紹了node.js中的fs.futimes方法使用說明,本文介紹了fs.futimes方法說明、語法、接收參數(shù)、使用實例和實現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • Node.js的特點詳解

    Node.js的特點詳解

    本文主要對Node.js的特點進行詳細介紹。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • 利用npm 安裝刪除模塊的方法

    利用npm 安裝刪除模塊的方法

    今天小編就為大家分享一篇利用npm 安裝刪除模塊的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • node.js中module模塊的功能理解與用法實例分析

    node.js中module模塊的功能理解與用法實例分析

    這篇文章主要介紹了node.js中module模塊的功能理解與用法,結合實例形式分析了node.js module模塊的基本功能、原理、用法及相關操作注意事項,需要的朋友可以參考下
    2020-02-02

最新評論