最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2019年10月15日 11:01:05   作者:機智的導演  
這篇文章主要介紹了node.js express框架實現(xiàn)文件上傳與下載功能,結(jié)合具體實例形式詳細分析了node.js express框架針對文件上傳與下載的前后臺相關(guān)實現(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',
    // 內(nèi)部根據(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);
        //設(shè)置需要壓縮得文件夾目錄 以及替換得名稱
        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程序設(shè)計有所幫助。

相關(guān)文章

  • node前端模板引擎Jade之標簽的基本寫法

    node前端模板引擎Jade之標簽的基本寫法

    這篇文章主要介紹了node前端模板引擎Jade之標簽的基本寫法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • Node工程的依賴包管理方式

    Node工程的依賴包管理方式

    在前端工程化中,JavaScript 依賴包管理是非常重要的一環(huán)。依賴包通常是項目所依賴的第三方庫、工具和框架等資源,它們能夠幫助我們減少重復開發(fā)、提高效率并且確保項目可以正確的運行。本文詳細介紹了Node工程的依賴包管理方式,感興趣的同學可以參考一下
    2023-04-04
  • Node.js中.pfx后綴文件的處理方法

    Node.js中.pfx后綴文件的處理方法

    這篇文章主要介紹了Node.js中.pfx后綴文件的處理方法,文中介紹的很詳細,對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。
    2017-03-03
  • 新入門node.js必須要知道的概念(必看篇)

    新入門node.js必須要知道的概念(必看篇)

    下面小編就為大家?guī)硪黄氯腴Tnode.js必須要知道的概念(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-08-08
  • nodejs開發(fā)一個最簡單的web服務器實例講解

    nodejs開發(fā)一個最簡單的web服務器實例講解

    在本篇文章里小編給大家整理的是關(guān)于nodejs開發(fā)一個最簡單的web服務器實例內(nèi)容,有需要的朋友們可以參考下。
    2020-01-01
  • npm?install安裝失敗報錯:The?operation?was?rejected?by?your?operating?system

    npm?install安裝失敗報錯:The?operation?was?rejected?by?your?

    這篇文章主要給大家介紹了關(guān)于npm?install安裝失敗報錯:The?operation?was?rejected?by?your?operating?system的相關(guān)資料,文中給出了多種解決方法供大家參考學習,需要的朋友可以參考下
    2023-04-04
  • 使用koa-log4管理nodeJs日志筆記的使用方法

    使用koa-log4管理nodeJs日志筆記的使用方法

    這篇文章主要介紹了使用koa-log4管理nodeJs日志筆記的使用方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11
  • Nginx設(shè)置為Node.js的前端服務器方法總結(jié)

    Nginx設(shè)置為Node.js的前端服務器方法總結(jié)

    在本篇文章中小編給大家分享了關(guān)于Nginx設(shè)置為Node.js的前端服務器的方法和實例,需要的朋友們學習下。
    2019-03-03
  • node.js 全局變量的具體使用

    node.js 全局變量的具體使用

    這篇文章主要介紹了node.js 全局變量的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • node.js中Buffer緩沖器的原理與使用方法分析

    node.js中Buffer緩沖器的原理與使用方法分析

    這篇文章主要介紹了node.js中Buffer緩沖器的原理與使用方法,結(jié)合實例形式分析了node.js Buffer緩沖器的基本概念、原理、創(chuàng)建、使用方法及相關(guān)操作注意事項,需要的朋友可以參考下
    2019-11-11

最新評論

富川| 肇庆市| 若尔盖县| 大新县| 芮城县| 阿图什市| 土默特左旗| 翁牛特旗| 普兰店市| 读书| 丰台区| 筠连县| 固始县| 石嘴山市| 许昌县| 梁山县| 和平区| 金湖县| 玉门市| 庄河市| 广饶县| 开封市| 荣昌县| 西畴县| 通榆县| 奉贤区| 枣庄市| 章丘市| 宿迁市| 萝北县| 陈巴尔虎旗| 芦山县| 会同县| 罗源县| 嘉荫县| 永嘉县| 阳泉市| 兴安盟| 图木舒克市| 察隅县| 三都|