Antd 4 Upload 图片上传(后端篇)
简介
这篇文章是Antd 4 Upload 图片上传(前端篇)的后续,使用nodejs
的express
搭建服务端,使用multer
处理文件上传,将前端上传的文件保存到服务端。
实现
创建一个新的文件夹作为后端服务:
初始化
npm
npm init -y
安装
express
和multer
npm i express multer
运行简单的服务
创建入口文件index.js
,创建一个简单的Web
服务:
const express = require('express')
const app = express()
const port = 8000
app.listen(port, () => {
console.log(`http://localhost:${port}`)
})
CORS 和 路由
1. CORS 跨域
由于前后端运行在不同的端口上,属于跨域请求,我就直接在后端做操作吧。
首先前端使用了Ant Design
的Upload
组件,它的action
属性是通过POST
请求提交FormData
数据,并且带有x-requested-with
请求头,那么我们先处理OPTION
检请求:
// 处理所有的 OPTIONS 预检请求
app.options('*', (req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000')
res.setHeader('Access-Control-Allow-Headers', 'x-requested-with')
next()
})
然后在写一个用来允许跨域的中间件cors
:
// 跨域中间件
const cors = (req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000')
next()
}
2. 路由
我们先定义好一个multer
用来文件上传的中间件,创建好文件夹public
,还有子文件夹uploads
:
const path = require('path')
const multer = require('multer')
const upload = multer({
storage: multer.diskStorage({
destination(req, file, cb) {
// 上传文件存在 public/uploads 下
cb(null, 'public/uploads')
},
filename(req, file, cb) {
// 使用时间戳作为上传的文件名
const extname = path.extname(file.originalname)
cb(null, Date.now() + extname)
}
})
})
然后添加前端请求的/upload
路由来处理文件上传,给前端返回JSON
数据,数据包含上传文件的文件名以及该文件在服务端的存储位置。
// 使用前面定义好的 cors 中间件和 upload 中间件
app.post('/upload', cors, upload.single('file'), (req, res) => {
const { file: { filename, path } } = req
res.json({
ok: true,
message: '图片上传成功',
data: {
name: filename,
url: path
}
})
})
然后我们还需要让这些上传的静态资源可以访问:
app.use('/public', express.static(path.join(__dirname, 'public')))
错误处理
比如前面的中间件upload
出现错误,我们可以在路由后面添加一个错误处理,返回给前端。
// 处理前面发生的错误
app.use((err, req, res, next) => {
console.log(err + '')
res.json({
ok: false,
message: '服务器错误'
})
})
补充:删除文件
添加一个删除上传的文件的API:
const fs = require('fs')
// 客户端请求体的JSON
app.use(express.json())
// delete删除请求
app.delete('/delete', cors, async (req, res,next) => {
const { path } = req.body
fs.unlink(path, (err) => {
if (err) return next(err)
res.json({
ok: true,
message: '删除图片成功'
})
})
})
这个路由使用了DELETE
请求方法,而且传了JSON
数据,我们需要修改下OPTIONS
处理的响应头:
app.options('*', (req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000')
// 追加允许的请求方法
res.setHeader('Access-Control-Allow-Methods', 'POST, DELETE')
// 客户端发了JSON 追加允许的请求头 Content-Type
res.setHeader('Access-Control-Allow-Headers', 'x-requested-with,Content-Type')
next()
})
完整代码
const express = require('express')
const app = express()
const port = 8000
const path = require('path')
const multer = require('multer')
const fs = require('fs')
// 文件上传
const upload = multer({
storage: multer.diskStorage({
destination(req, file, cb) {
// 上传文件存在 public/uploads 下
cb(null, 'public/uploads')
},
filename(req, file, cb) {
// 使用时间戳作为上传的文件名
const extname = path.extname(file.originalname)
cb(null, Date.now() + extname)
}
})
})
// 静态资源
app.use('/public', express.static(path.join(__dirname, 'public')))
// 处理所有的 OPTIONS 预检请求
app.options('*', (req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000')
// 追加允许的请求方法
res.setHeader('Access-Control-Allow-Methods', 'POST, DELETE')
// 客户端发了JSON 追加允许的请求头 Content-Type
res.setHeader('Access-Control-Allow-Headers', 'x-requested-with,Content-Type')
next()
})
// 跨域中间件
const cors = (req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000')
next()
}
// 使用前面定义好的 cors 中间件和 upload 中间件
app.post('/upload', cors, upload.single('file'), (req, res) => {
const { file: { filename, path } } = req
res.json({
ok: true,
message: '图片上传成功',
data: {
name: filename,
url: path
}
})
})
// 解析客户端请求的JSON数据
app.use(express.json())
// 删除文件
app.delete('/delete', cors, async (req, res, next) => {
// const { path } = req.body
const path = '11'
fs.unlink(path, (err) => {
if (err) return next(err)
res.json({
ok: true,
message: '删除图片成功'
})
})
})
// 处理前面发生的错误
app.use((err, req, res, next) => {
console.log(err + '')
res.json({
ok: false,
message: '服务器错误'
})
})
app.listen(port, () => {
console.log(`http://localhost:${port}`)
})
版权声明:
Anand's Blog文章皆为站长Anand Zhang原创内容,转载请注明出处。
包括商业转载在内,注明下方要求的文章出处信息即可,无需联系站长授权。
请尊重他人劳动成果,用爱发电十分不易,谢谢!
请注明出处:
本文出自:Anand's Blog