npm i express multer -S
前端表单
- enctype必须指定multipart/form-data,因为multer只支持这种。
- name的值“logo”对应服务器upload.single中的“logo”。
<form action="/postFile" method="post" enctype="multipart/form-data">
<input id="postFile" type="file" name="logo">
<button type="submit">上传button>
form>
后端服务器文件
- dest对应上传的文件的目录地址。
- upload.single的值“logo”对应前端name中的“logo”。
import express from 'express'
import multer from 'multer'
const app = express()
const upload = multer({ dest: 'uploads/' })
app.post('/postFile', upload.single('logo'), (req, res) => {
res.send(req.file)
})
app.listen(3000, () => {
console.log('服务器开启中')
})
我们发现虽然上传了,但是文件不是我们想要的样子,没有后缀,也不知道是我们上传的图片文件。
我们可以对multer进行详细的配置。
- destination配置上传文件的位置
- filename配置文件名,可以利用file上传文件的内容进行配置:
import express from 'express'
import multer from 'multer'
const app = express()
// const upload = multer({ dest: 'uploads/' })
const upload = multer({
storage: multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads/')
},
filename: function (req, file, cb) {
// fieldname是表单的name值,也就是我们设定的“logo”,
// originalname是文件上传时的名字,可以根据它获取后缀,
// encoding,mimetype 我就不详细介绍了,可以自行输出查看。
const { fieldname, originalname, encoding, mimetype } = file
const after = originalname.split('.')[1] ? '.' + originalname.split('.')[1] : '.jpg'
cb(null, fieldname + after);
}
})
})
app.post('/postFile', upload.single('logo'), (req, res) => {
res.send(req.file)
})
app.listen(3000, () => {
console.log('服务器开启中')
})
后端问题解决了我们看看前端的问题,表单上传文件不仅拓展差,还会跳转新页面,令人头疼。
我们肯定更希望用js中的fetch手动上传。如果还不会使用fetch可以先移步:fetch异步请求使用详解
我们去掉form表单,自定义一个上传事件。
- 我的前端页面在8080端口,也做了nginx代理请求到3000端口,你们可以自行修改成自己的请求。
- body.append(‘logo’, file)这里的作为key的“logo”代替了原本表单中的name值“logo”的作用。
- 虽然是post请求,但是
不要
添加请求头’Content-Type’: ‘multipart/form-data’,上传文件时post已经自动帮你识别了,再加就要报错了。
<body>
<input id="postFile" type="file" name="logo">
<button type="button" onclick="upload()">上传button>
body>
<script>
const upload = async () => {
const body = new FormData()
const file = document.getElementById('postFile').files[0]
if (file) {
body.append('logo', file)
const response = await fetch('http://localhost:8080/postFile', {
method: 'post',
body
})
const res = await response.json()
console.log(res)
} else {
alert('请选择文件!')
}
}
script>
前端表单
- input加上multiple,支持多文件。
- 因为现在是多文件了,就不直接取文件,我们先获取用id获取dom,遍历添加进body,记得“logo”要对应后台“logo”。
<body>
<input id="postFile" type="file" name="logo" multiple>
<button type="sub" onclick="upload()">上传</button>
</body>
<script>
const upload = async () => {
const body = new FormData()
const postFile = document.getElementById('postFile')
if (postFile.files[0]) {
for (const file of postFile.files) {
body.append('logo', file)
}
const response = await fetch('http://localhost:8080/postFile', {
method: 'post',
body
})
const res = await response.json()
console.log(res)
} else {
alert('请选择文件!')
}
}
</script>
后端服务器文件
- upload.single(‘logo’)改成upload.array(‘logo’, 3),后面的数字是限制上传文件数。
- 命名我们就用本来的名字,好区分不同的文件。
import express from 'express'
import mysql from 'mysql'
import multer from 'multer'
const app = express()
// const upload = multer({ dest: 'uploads/' })
const upload = multer({
storage: multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads/')
},
filename: function (req, file, cb) {
const { fieldname, originalname, encoding, mimetype } = file
// const after = originalname.split('.')[1] ? '.' + originalname.split('.')[1] : '.jpg'
cb(null, originalname);
}
})
})
app.post('/postFile', upload.array('logo', 3), (req, res) => {
res.send(req.files)
})
app.listen(3000, () => {
console.log('服务器开启中')
})
大功告成,有帮助的话不妨点个赞吧,如果有什么问题可以评论区提出,会及时更新解决。