1、我们之前可以用body-parser
或者querystring
等模块去获取和处理get
和post
里面的数据,但是这些数据如果是上传的一个或多个文件呢?这个时候,就需要用multer
了。建议直接访问官方文档,因为每个版本的使用不太一样:https://www.npmjs.com/package/multer。
先准备一个html页面,下面的页面是最终的页面,第一次和第二次做实验的时候,其实没有那么多上传的控件,如果有这些控件,但是没有在代码里处理的话,会报错。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传测试title>
head>
<body>
<form action="http://localhost:1337/upload" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"><br>
请上传头像1:<input type="file" name="avatar"><br>
请上传头像2:<input type="file" name="avatar"><br>
请上传头像3:<input type="file" name="avatar"><br>
请上传背景:<input type="file" name="bg"><br>
<input type="submit" value="提交">
form>
body>
html>
2、我们先看第一种,只上传一个文件的情况,也就是上面的那个html里面我们只用了第一个上传控件,其他的先注释掉:
用户名:type="text" name="username">
请上传头像1:type="file" name="avatar">
const express = require('express');
const multer = require('multer');
const expressStatic = require('express-static');
// 这个就是文件上传的存储目录
var upload = multer({dest:'./www/upload'});
var server = express();
server.post('/upload',upload.single('avatar'),function(req,res){
// 因为是single,所以是一个,需要指定name,下面接收也只用file
console.log(req.file);
// 还可以接收一并过来的body数据,multer其实包含了之前的解析post里body的功能
console.log(req.body);
res.send('upload success.');
});
server.use(expressStatic('./www'));
server.listen(1337);
我们看看得到的是什么样的结果,所以可以通过originalname
和mimetype
拿到后缀,可以通过filename
和path
得到最终的文件名称和路径:
{ fieldname: 'avatar',
originalname: '7.png',
encoding: '7bit',
mimetype: 'image/png',
destination: './www/upload',
filename: 'e70d501dd1263675410c32bd8304be07',
path: 'www\\upload\\e70d501dd1263675410c32bd8304be07',
size: 38892 }
{ username: 'eric' }
3、第二种情况就是上传相同的名称的好几个文件,比如上传朋友圈的那种9张图。
用户名:type="text" name="username">
请上传头像1:type="file" name="avatar">
请上传头像2:type="file" name="avatar">
请上传头像3:type="file" name="avatar">
const express = require('express');
const multer = require('multer');
const expressStatic = require('express-static');
const pathLib = require('path');
const fs = require('fs');
var upload = multer({dest:'./www/upload'});
var server = express();
// 这边的数字4不能比html里面的name='avatar'的数量少,否则会报错,这边相当于maxCount,接收几个名字叫做avatar的文件
server.post('/upload',upload.array('avatar',4),function(req,res){
// 因为是single,所以是一个,需要指定name,下面接收也只用file
console.log(req.files);
for (var i = 0; i var newName = req.files[i].path + pathLib.parse(req.files[i].originalname).ext;
fs.rename(req.files[i].path,newName,function(err){
if (err) {
console.log("rename failure.");
}else{
console.log("rename success.");
}
});
}
console.log(req.body);
res.send('upload success.');
});
server.use(expressStatic('./www'));
server.listen(1337);
结果是一个数组,可以通过for
循环,再利用fs
的rename
方法对所有的文件加个后缀:
[ { fieldname: 'avatar',
originalname: '7.png',
encoding: '7bit',
mimetype: 'image/png',
destination: './www/upload',
filename: '134594327c1d892bdc7c23f985e443e1',
path: 'www\\upload\\134594327c1d892bdc7c23f985e443e1',
size: 38892 },
{ fieldname: 'avatar',
originalname: '6.png',
encoding: '7bit',
mimetype: 'image/png',
destination: './www/upload',
filename: '3e8ff491e5b0a4fe2993b63736040bf2',
path: 'www\\upload\\3e8ff491e5b0a4fe2993b63736040bf2',
size: 31146 },
{ fieldname: 'avatar',
originalname: '5.png',
encoding: '7bit',
mimetype: 'image/png',
destination: './www/upload',
filename: 'e89deeea8a7b44b2f5226f19bfa0eef3',
path: 'www\\upload\\e89deeea8a7b44b2f5226f19bfa0eef3',
size: 57466 } ]
{ username: 'aaa' }
rename success.
rename success.
rename success.
4、还有一种比较复杂的情况,就是有很多文件上传吗,而且还不一定是同一个类别(也就是name值可能不同):
用户名:type="text" name="username">
请上传头像1:type="file" name="avatar">
请上传头像2:type="file" name="avatar">
请上传头像3:type="file" name="avatar">
请上传背景:type="file" name="bg">
const express = require('express');
const multer = require('multer');
const expressStatic = require('express-static');
const pathLib = require('path');
const fs = require('fs');
var upload = multer({dest:'./www/upload'});
var server = express();
// 如果出了3个name='avatar'的上传之外,还有一个name='bg'的上传,那么用下面这种方法
server.post('/upload',upload.fields([{name:'avatar',maxCount:3},{name:'bg',maxCount:1}]),function(req,res){
console.log(req.files);
for(var i=0;i'avatar'].length;i++){
var newName = req.files['avatar'][i].path + pathLib.parse(req.files['avatar'][i].originalname).ext;
fs.rename(req.files['avatar'][i].path,newName,function(err){
if(err){
console.log('upload failure.')
}else{
console.log('upload success.')
}
});
}
var newName = req.files['bg'][0].path + pathLib.parse(req.files['bg'][0].originalname).ext;
fs.rename(req.files['bg'][0].path,newName,function(err){
if (err) {
console.log('upload failure.')
}else{
console.log('upload success.')
}
});
console.log(req.body);
res.send('upload success.');
});
server.use(expressStatic('./www'));
server.listen(1337);
我们看一下结果,它其实是个字典,大的字典的key
就是每个文件的name
,而这个name
对应的value
是一个数组,不管里面有个文件,都是数组,那么久好办了,要rename
的话,那么久一个个的name
来处理就行了:
{ avatar:
[ { fieldname: 'avatar',
originalname: '7.png',
encoding: '7bit',
mimetype: 'image/png',
destination: './www/upload',
filename: '0637965a24bc41fa550008d31f7f03fb',
path: 'www\\upload\\0637965a24bc41fa550008d31f7f03fb',
size: 38892 },
{ fieldname: 'avatar',
originalname: '6.png',
encoding: '7bit',
mimetype: 'image/png',
destination: './www/upload',
filename: '93c049c585a84fb91fce0d4920b5724d',
path: 'www\\upload\\93c049c585a84fb91fce0d4920b5724d',
size: 31146 },
{ fieldname: 'avatar',
originalname: '5.png',
encoding: '7bit',
mimetype: 'image/png',
destination: './www/upload',
filename: '237ed62f7016cfb4b4e9495d3beb0199',
path: 'www\\upload\\237ed62f7016cfb4b4e9495d3beb0199',
size: 57466 } ],
bg:
[ { fieldname: 'bg',
originalname: 'jquery1.42.min.js',
encoding: '7bit',
mimetype: 'application/javascript',
destination: './www/upload',
filename: '9d2613cc8c8d2dd3e23a7e523d3d3ba3',
path: 'www\\upload\\9d2613cc8c8d2dd3e23a7e523d3d3ba3',
size: 72326 } ] }
{ username: 'eric' }
upload success.
upload success.
upload success.
upload success.