概述
上传文件是web开发中经常要用到的功能。这篇文章就是介绍在Express
中如何使用multer
中间件进行文件上传。
使用的技术栈
开发过程
1. 先把项目构造出来
首先用一行代码,把环境搭起来。
npm install --save express multer
然后新建项目的入口文件app.js
,代码如下:
const path = require('path')
const express = require('express');
const app = express();
// 静态化资源
app.use(express.static(path.join(__dirname, 'public')))
app.get('/', (req, res) => {
res.send('首页');
});
app.listen(3000, () => console.log('服务器已启动!'));
在命令行启动项目,在浏览器中就可以看到首页面:
node app
![](https://img.haomeiwen.com/i150175/8864517a4f7f16b8.png)
2. 引入前端用到的上传页面和脚本
之后新建index.html
和demo.js
文件,目录结构,如图所示:
![](https://img.haomeiwen.com/i150175/728ed02838a37496.png)
index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>首页</title>
</head>
<body>
<input type="file" id="myFile"/>
<script src="/js/demo.js"></script>
</body>
</html>
demo.js
(为演示方便,代码并没有考虑fetch
的兼容性问题):
document.querySelector('#myFile').onchange = event => {
const e = event || window.event;
const target = e.target || e.srcElement;
const file = target.files[0];
const formdata = new FormData();
formdata.append('myFile', file); // 添加上传的文件对象
fetch('/upload', { // 上传路径
method: 'POST',
body: formdata,
})
.then(res => res.json())
.then(res => alert(res.message))
.catch(err => console.dir(err));
};
这时我们再回头来修改app.js
的首页路由代码,以加载index.html
页面:
const fs = require('fs');
app.get('/', (req, res) => {
const html = fs.readFileSync('./view/index.html', { encoding: 'utf8' }); // 加载进行上传操作的页面
res.send(html);
});
此时,首页如图所示:
![](https://img.haomeiwen.com/i150175/f69434f1d3dc8c19.png)
3. 用multer吧
好了,重头戏来了。
为了出彩,我们必须要修改一下app.js
了,把multer
模块引进来,并用它来接收上传的文件。光说不练,瞎扯淡,少废话,先上代码:
const fs = require('fs');
const path = require('path')
const express = require('express');
const multer = require('multer');
const app = express();
const storage = multer.diskStorage({ // 设置multer参数,个性化指定上传目录和文件名
destination: (req, file, cb) => {
const uploadFloder = './myUpload'; // 保存上传文件的目录
try {
fs.accessSync(uploadFloder);
} catch (error) {
fs.mkdirSync(uploadFloder);
}
cb(null, uploadFloder);
},
filename: (req, file, cb) => {
cb(null, file.originalname);
}
});
const upload = multer({ // 实例化multer对象
storage: storage
});
// 静态化资源
app.use(express.static(path.join(__dirname, 'public')))
app.get('/', (req, res) => {
const html = fs.readFileSync('./view/index.html', { encoding: 'utf8' }); // 进行上传操作的页面
res.send(html);
});
// 响应上传请求
app.post('/upload', upload.single('myFile'), (req, res) => {
res.send({
message: '响应了请求'
});
});
app.listen(3000, () => console.log('服务器已启动!'));
这样就可以保存上传的文件了,有图有真相:
![](https://img.haomeiwen.com/i150175/f19838bf18080bcf.png)
项目的结构:
![](https://img.haomeiwen.com/i150175/33f2b08857c26144.png)
好了,上传成功了,真相图也看了,现在该讲讲上面这些代码都是干什么用的了。
const multer = require('multer');
引入
multer
中间件。
const storage = multer.diskStorage({ // 设置multer参数,个性化指定上传目录和文件名
destination: (req, file, cb) => {
const uploadFloder = './myUpload'; // 保存上传文件的目录
try {
fs.accessSync(uploadFloder);
} catch (error) {
fs.mkdirSync(uploadFloder);
}
cb(null, uploadFloder);
},
filename: (req, file, cb) => {
cb(null, file.originalname);
}
});
在此处进行个性化的设置,指定上传的目录和文件名。这一步并不是必须要做的。如果不设置,则生成的文件名是一个哈希值。
const upload = multer({ // 实例化multer对象
storage: storage
});
使用刚才的设置来实例化对象。如果不个性化设置,则必须要使用
dest
属性来指定上传的路径,就像这样:const upload = multer({ // 实例化multer对象 dest: './myUpload' // 保存上传文件的目录 });
app.post('/upload', upload.single('myFile'), (req, res) => {
res.send({
message: '响应了请求'
});
});
使用
single()
方法来响应单文件上传操作。注意:此处的myFile
参数是前端上传的文件名,必须要一致。
基因突变
如何上传多个文件?
上面的例子演示了单文件的上传操作,那么能不能同时上传多个文件呢?那肯定是能啊,只要把single()
方法换成array(文件名, 最大文件个数)
就行了。
首先,我们先向页面添加multiple
属性,使其支持多文件上传:
<input type="file" id="myFile" multiple="multiple" />
然后修改demo.js
文件,将上传的多个文件放入formdata
中,这些文件都使用同一个文件名myFile
,代码如下:
document.querySelector('#myFile').onchange = event => {
const e = event || window.event;
const target = e.target || e.srcElement;
const files = target.files;
const formdata = new FormData();
for (const file of files) {
// 添加上传的文件对象
// formdata的append()方法有一个特点,
// 它会把新值添加到已有值集合的后面,而不会用新值覆盖已有的值。
// 这样就能达到用同一文件名,添加多个文件的目地。
formdata.append('myFile', file);
}
fetch('/upload', { // 上传文件
method: 'POST',
body: formdata,
})
.then(res => res.json())
.then(res => alert(res.message))
.catch(err => console.dir(err));
};
最后,修改app.js
文件,使用array()
方法保存上传的多个文件,修改如下:
app.post('/upload', upload.array('myFile', 10), (req, res) => {
res.send({
message: '响应了请求'
});
});
就是这么简单,就是这么拉风。
网友评论