欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

背景

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

功能實(shí)現(xiàn)

  • 前臺(tái)部分

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

  $scope.fileName = "";
  //創(chuàng)建上傳附件的對(duì)象
  var $list = $("#thelist");
  var uploader = WebUploader.create({
    // 選完文件后,是否自動(dòng)上傳。
    auto: false,
    // swf文件路徑
    swf: '../../../lib/webUploader/Uploader.swf',
    // 文件接收服務(wù)端。
    server: '/publishUploadFile',
    // 內(nèi)部根據(jù)當(dāng)前運(yùn)行是創(chuàng)建,可能是input元素,也可能是flash.
    pick : {
      id : '#filePicker',
      //只能選擇一個(gè)文件上傳
      multiple: false
    },
    // pick :'#filePicker',
    method: 'POST',
  });
  uploader.on('fileQueued', function (file) {
    $scope.fileName = file.name;
    $list.html("");
    $list.html(file.name);
  });

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

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

  • 后臺(tái)部分

路由就不詳細(xì)說明了,主要注意的是下載的接口我都是使用的get請(qǐng)求,這樣前臺(tái)在請(qǐng)求的時(shí)候直接新打開一個(gè)窗口拼接了相應(yīng)的參數(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ā)布端導(dǎo)出附件
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解壓報(bào)錯(cuò)
      // 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時(shí)使用download下載完的壓縮包解壓會(huì)報(bào)錯(cuò),使用第二種方法完美解決。

然后是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);
    //將上傳的文件從臨時(shí)目錄拷貝到指定的目錄下
    var fileReadStream = fs.createReadStream(file.path);
    var fileWriteStream = fs.createWriteStream(uploadFolder + "/" + file.originalname);
    fileReadStream.pipe(fileWriteStream);
    fileWriteStream.on('close', function () {
      // 刪除臨時(shí)目錄下面的文件
      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;
    //附件名稱或標(biāo)題
    var name = req.query.name;
    if (id && name) {
      //名稱過長的話,截取前25個(gè)字符
      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ā)送的時(shí)間
    var msgSendTime = req.body.msgSendTime.slice(0, 10);
    //消息的標(biāo)題
    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ā)送時(shí)間
    var index = file.originalname.lastIndexOf(".");
    var fileName = file.originalname.substr(0, index) + '-' + msgSendTime + "";
    var suffix = file.originalname.substr(index, file.originalname.length - 1);
    //將上傳的文件從臨時(shí)目錄拷貝到指定的目錄下
    var fileReadStream = fs.createReadStream(file.path);
    var fileWriteStream = fs.createWriteStream(uploadFolder + "/" + fileName + "." + suffix);
    fileReadStream.pipe(fileWriteStream);
    fileWriteStream.on('close', function () {
      //刪除臨時(shí)目錄下面的文件
      toolUtil.emptyDir(file.destination);
    });
    fn(null, {"data": "", "message": "上傳成功", "error_code": 200});
  } catch (e) {
    fn(e, {"data": "", "message": "上傳失敗", "error_code": e.message});
  }
};
/**
 * 導(dǎo)出消息的附件文件
 * @param req
 * @param fn
 */
MessageManager.prototype.exportFile = function (req, fn) {
  try {
    //消息ID
    var id = req.query.id;
    //消息名稱或標(biāo)題
    var name = req.query.name;
    if (id && name) {
      //名稱過長的話,截取前25個(gè)字符
      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 {
        //生成得臨時(shí)zip文件目錄
        var zipPath = path.join(__dirname, '../../upload/temp.zip');
        var archive = archiver('zip', {
          // Sets the compression level.
          zlib: {level: 9}
        });
        //創(chuàng)建臨時(shí)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的代碼,這個(gè)單獨(dú)做為一個(gè)js文件維護(hù)。

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);
    }
  });
};

希望本文所述對(duì)大家node.js程序設(shè)計(jì)有所幫助。

相關(guān)文章

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

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

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

    搭建一個(gè)Koa后端項(xiàng)目腳手架的方法步驟

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

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

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

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

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

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

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

    Node 創(chuàng)建第一個(gè)服務(wù)器應(yīng)用的操作方法

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

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

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

    Node.js的特點(diǎn)詳解

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

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

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

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

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

最新評(píng)論