最近,自己玩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>