nodejs檔案上傳處理模組formidable

CopperDong發表於2018-02-28

本文轉自http://itbilu.com/nodejs/npm/NkGKcF14.html

 在web開發中,經常遇到處理檔案上傳的情況。而express框架在4.0版本後就不在支援req.files接收上傳檔案,對於檔案上傳,需要加multipart格式資料處理的中介軟體。multipart資料處理中介軟體有:busboy, multer, formidable, multiparty, connect-multiparty, pez等。本站使用了formidable外掛,比較簡單易用。
formidable是一個用於處理檔案、圖片、視訊等資料上傳的模組,支援GB級上傳資料處理,支援多種客戶端資料提交。有極高的測試覆蓋率,非常適合在生產環境中使用。

安裝

formidable是一個輕量級的應用包,可以不依賴於express等框架單獨使用,也可以整合到exress框架中使用。安裝命令如下: 

[plain] view plain copy
  1. npm install formidable@latest  

 使用

在nodejs原生環境中使用formidable。 

[javascript] view plain copy
  1. var formidable = require('formidable'),  
  2.     http = require('http'),  
  3.     util = require('util');  
  4.   
  5. //用http模組建立一個http服務端   
  6. http.createServer(function(req, res) {  
  7.   if (req.url == '/upload' && req.method.toLowerCase() === 'post') {  
  8.     // 處理上傳的檔案  
  9.     var form = new formidable.IncomingForm();  
  10.    
  11.     form.parse(req, function(err, fields, files) {  
  12.       res.writeHead(200, {'content-type''text/plain'});  
  13.       res.write('received upload:\n\n');  
  14.       res.end(util.inspect({fields: fields, files: files}));  
  15.     });  
  16.    
  17.     return;  
  18.   }  
  19.    

 上傳後,響應結果如下 
[javascript] view plain copy
  1. received upload:  
  2.   
  3. { fields: { title: 'title的內容' },  
  4.   files:      //所有type="file"型別的資料物件  
  5.    { upload:   
  6.       { domain: null,  
  7.         _events: {},  
  8.         _maxListeners: 10,  
  9.         size: 41966,             //檔案大小  
  10.         path: '/var/folders/1k/86kq55_n4_q2tckwz9mb5wyr0000gn/T/upload_ecbf965abc1e14c2ffc86875c2f5eaa8',   //檔案儲存路徑  
  11.         name: 'avatar.jpg',     //上傳前的檔名  
  12.         type: 'image/jpeg',    //檔案型別  
  13.         hash: null,  
  14.         lastModifiedDate: Sat May 16 2015 10:38:57 GMT+0800 (CST),  
  15.         _writeStream: [Object] } } }  

 常用API

建立一個incoming form例項 
[javascript] view plain copy
  1. var form = new formidable.IncomingForm()  

 設定incoming form fields(fileds指除type="file"外的其它接收資料)編碼 
[javascript] view plain copy
  1. form.encoding = 'utf-8';  

設定檔案接收後儲存的資料夾。此資料夾一般為上傳後的臨時資料夾,上傳後呼叫 fs.rename()對檔案進行移動及重新命名。預設儲存路徑為os.tmpDir() 
[javascript] view plain copy
  1. form.uploadDir = "/my/dir";  
設定上傳後檔案是否使用原副檔名,預設值為false。如果希望儲存到form.uploadDir中的檔案使用原副檔名時,需要將此項設定為true 

[javascript] view plain copy
  1. form.keepExtensions = false;  

 'multipart'或'urlencoded'型別的請求在formidable都支援,可通過上傳檔案的type屬性檢視檔案型別 
[javascript] view plain copy
  1. form.type  
 設定上傳檔案的大小,預設值為2M 
[javascript] view plain copy
  1. form.maxFieldsSize = 2 * 1024 * 1024;  
 設定最大可接收欄位數,用於防止記憶體溢位,預設值為1000 
[javascript] view plain copy
  1. form.maxFields = 1000;  
 是否對上傳檔案進行hash較驗,可設定為'sha1' 或 'md5' 
[javascript] view plain copy
  1. form.hash = false;  

在express中使用formidable

在express框架中使用formidable,需要一個接收檔案提交的路由。以下示例為一個接收使用者頭像提交的路由
[javascript] view plain copy
  1. router.post("/user/avatar", user.avatar);  

 路由對應的接收提交資料的方法
[javascript] view plain copy
  1. //設定頭像  
  2. exports.avatar = function(req, res, next) {  
  3.     var form = new formidable.IncomingForm();  
  4.     form.uploadDir = path.join(__dirname, 'tmp');   //檔案儲存的臨時目錄為當前專案下的tmp資料夾  
  5.     form.maxFieldsSize = 1 * 1024 * 1024;  //使用者頭像大小限制為最大1M    
  6.     form.keepExtensions = true;        //使用檔案的原副檔名  
  7.     form.parse(req, function (err, fields, file) {  
  8.         var filePath = '';  
  9.         //如果提交檔案的form中將上傳檔案的input名設定為tmpFile,就從tmpFile中取上傳檔案。否則取for in迴圈第一個上傳的檔案。  
  10.         if(file.tmpFile){  
  11.             filePath = file.tmpFile.path;  
  12.         } else {  
  13.             for(var key in file){  
  14.                 if( file[key].path && filePath==='' ){  
  15.                     filePath = file[key].path;  
  16.                     break;  
  17.                 }  
  18.             }  
  19.         }  
  20.         //檔案移動的目錄資料夾,不存在時建立目標資料夾  
  21.         var targetDir = path.join(__dirname, 'upload');  
  22.         if (!fs.existsSync(targetDir)) {  
  23.             fs.mkdir(targetDir);  
  24.         }  
  25.         var fileExt = filePath.substring(filePath.lastIndexOf('.'));  
  26.         //判斷檔案型別是否允許上傳  
  27.         if (('.jpg.jpeg.png.gif').indexOf(fileExt.toLowerCase()) === -1) {  
  28.             var err = new Error('此檔案型別不允許上傳');  
  29.             res.json({code:-1, message:'此檔案型別不允許上傳'});  
  30.         } else {  
  31.             //以當前時間戳對上傳檔案進行重新命名  
  32.             var fileName = new Date().getTime() + fileExt;  
  33.             var targetFile = path.join(targetDir, fileName);  
  34.             //移動檔案  
  35.             fs.rename(filePath, targetFile, function (err) {  
  36.                 if (err) {  
  37.                     console.info(err);  
  38.                     res.json({code:-1, message:'操作失敗'});  
  39.                 } else {  
  40.                     //上傳成功,返回檔案的相對路徑  
  41.                     var fileUrl = '/upload/' + fileName;  
  42.                     res.json({code:0, fileUrl:fileUrl});  
  43.                 }  
  44.             });  
  45.         }  
  46.     });  
  47. }  





相關文章