基於NodeJs的文件上傳
最近,自己玩nodeJs,用上了Express框架,小白。上傳文件,查了寫資料。
發現了有req.files
這個接口,然后試了下。
使用req.files
Express默認的上傳路徑為/tmp
。如果是windows系統,會有報錯。所以,你可以指定上傳的臨時目錄:
//默認臨時目錄 //app.use(express.bodyParser()); //修改自定義目錄,V2.5.4版本之后支持 app.use(express.bodyParser({uploadDir:'./uploads'}));
使用方法:
前端:
<form action="/uploadImg" method="post" enctype="multipart/form-data"> <h2>單圖上傳</h2> <input type="file" name="logo"> <input type="submit" value="提交"> </form>
nodeJs
app.post('/uploadImg', function(req, res, next) { console.log(req.body); console.log(req.files); //獲取詳細信息 var file = req.files.logo;//From the name console.log('文件類型:%s', file.type); console.log('原始文件名:%s', file.name); console.log('文件大小:%s', file.size); console.log('文件保存路徑:%s', file.path); });
其中,通過定義的對象名來獲取具體的file對象。常用屬性:
- size ---- 文件大小(bytes)
- path ---- 文件上傳后的路徑
- name ---- 文件的原始文件名稱.
- type ----文件類型
同時,通過express上傳的目錄都是臨時目錄,如果要進行永久性保存,還需要將其移動到項目的文件存放目錄下。
這里有一個實例:
// 移動文件需要使用fs模塊 var fs = require('fs'); app.post('/file-upload', function(req, res) { // 獲得文件的臨時路徑 var tmp_path = req.files.thumbnail.path; // 指定文件上傳后的目錄 - 示例為"images"目錄。 var target_path = './public/images/' + req.files.thumbnail.name; // 移動文件 fs.rename(tmp_path, target_path, function(err) { if (err) throw err; // 刪除臨時文件夾文件, fs.unlink(tmp_path, function() { if (err) throw err; res.send('File uploaded to: ' + target_path + ' - ' + req.files.thumbnail.size + ' bytes'); }); }); };
但是發現,express項目運行出錯:
Error: Most middleware (like bodyParser) is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.
查了一下官方文檔,才發現:
In Express 4, req.files is no longer available on the req object by default. To access uploaded files on the req.files object, use a multipart-handling middleware like busboy, multer, formidable, multiparty, connect-multiparty, or pez.
解決問題,使用中間件。
支持文件上傳中間件
因為時間有限,並沒有做很深入的了解,看了下busboy的使用方法,感覺略麻煩。然后去multer看了下,發現其是在busboy上進行了封裝,使其更加高效。決定使用它進行更新。
安裝multer
npm install express multer multer --save
下面實例均來自Nodejs進階:基於express+multer的文件上傳
單圖上傳
nodeJs
var fs = require('fs'); var express = require('express'); var multer = require('multer') var app = express(); var upload = multer({ dest: 'upload/' }); // 單圖上傳 app.post('/upload', upload.single('logo'), function(req, res, next){ res.send({ret_code: '0'}); }); app.get('/form', function(req, res, next){ var form = fs.readFileSync('./form.html', {encoding: 'utf8'}); res.send(form); }); app.listen(3000);
html:
<form action="/upload-single" method="post" enctype="multipart/form-data"> <h2>單圖上傳</h2> <input type="file" name="logo"> <input type="submit" value="提交"> </form>
點擊提交之后,圖片會直接下載到服務器的指定目錄下,也就是upload/
目錄。
多圖上傳
nodeJs
var fs = require('fs'); var express = require('express'); var multer = require('multer') var app = express(); var upload = multer({ dest: 'upload/' }); // 多圖上傳 app.post('/upload', upload.array('logo', 2), function(req, res, next){ res.send({ret_code: '0'}); }); app.get('/form', function(req, res, next){ var form = fs.readFileSync('./form.html', {encoding: 'utf8'}); res.send(form); }); app.listen(3000);
html:
<form action="/upload-multi" method="post" enctype="multipart/form-data"> <h2>多圖上傳</h2> <input type="file" name="logo"> <input type="file" name="logo"> <input type="submit" value="提交"> </form>
獲得圖片信息
通過multer,我們可以獲取:
- 原始文件名
- 文件大小
- 本地保存路徑
- 文件類型
與老的方法相似,multer將文件信息一並保存到了file對象中。
nodeJs
var fs = require('fs'); var express = require('express'); var multer = require('multer') var app = express(); var upload = multer({ dest: 'upload/' }); // 單圖上傳 app.post('/upload', upload.single('logo'), function(req, res, next){ var file = req.file; console.log('文件類型:%s', file.mimetype); console.log('原始文件名:%s', file.originalname); console.log('文件大小:%s', file.size); console.log('文件保存路徑:%s', file.path); res.send({ret_code: '0'}); }); app.get('/form', function(req, res, next){ var form = fs.readFileSync('./form.html', {encoding: 'utf8'}); res.send(form); }); app.listen(3000);
html:
<form action="/upload" method="post" enctype="multipart/form-data"> <h2>單圖上傳</h2> <input type="file" name="logo"> <input type="submit" value="提交"> </form>
簡單嘗試之后,發現上傳的文件有兩個特性:
- 文件名是一個hash字符串。而且上傳同一個文件名稱不一樣。(之后再看源碼,理解一下)
- 文件是無格式的,也就是說沒有后綴名
筆者給其加入后綴名后即可瀏覽。所以現在需要做的就是自定義文件名。
自定義上傳路徑和文件名
自定義本地保存的路徑,修改dest配置項。
var upload = multer({ dest: 'upload/' });
自定義文件名,需要使用mukter的Storage參數,來對資源的保存路徑和文件名進行個性化設置。
- destination:設置資源的保存路徑。注意,如果沒有這個配置項,默認會保存在 /tmp/uploads 下。此外,路徑需要自己創建。
- filename:設置資源保存在本地的文件名。
nodeJs
var fs = require('fs'); var express = require('express'); var multer = require('multer') var app = express(); var createFolder = function(folder){ try{ fs.accessSync(folder); }catch(e){ fs.mkdirSync(folder); } }; var uploadFolder = './upload/'; createFolder(uploadFolder); // 通過 filename 屬性定制 var storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, uploadFolder); // 保存的路徑,備注:需要自己創建 }, filename: function (req, file, cb) { // 將保存文件名設置為 字段名 + 時間戳,比如 logo-1478521468943 cb(null, file.fieldname + '-' + Date.now()); } }); // 通過 storage 選項來對 上傳行為 進行定制化 var upload = multer({ storage: storage }) // 單圖上傳 app.post('/upload', upload.single('logo'), function(req, res, next){ var file = req.file; res.send({ret_code: '0'}); }); app.get('/form', function(req, res, next){ var form = fs.readFileSync('./form.html', {encoding: 'utf8'}); res.send(form); }); app.listen(3000);
html:
<form action="/upload" method="post" enctype="multipart/form-data"> <h2>單圖上傳</h2> <input type="file" name="logo"> <input type="submit" value="提交"> </form>