基于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>