用nodejs的formidable上传图片,第一张上传成功,再上传发生错误Can't set headers after they are sent
- 1 错误表现
图上的结果是:我在mavoneditor编辑器里面上传第一张图片时,可以正确从服务端返回图片的网络地址,再上传第二张图片的时候,就报错了,图片地址任然是本地地址。
- 2 服务端的报错
从信息上也看出我第一次post /upload 是成功的,前端也正确get 到了服务端图片地址,第二次post却发生错误了,错误信息 Can't set headers after they are sent
但第二次上传的图片却已经上传到了服务端
虽然从图上看不出来,但upload里面的确多了一张图片
- 3 代码
上传图片的前端代码
<el-form-item label="商品详情" prop="info">
<mavon-editor ref="md" @imgAdd="$imgAdd" @imgDel="$imgDel" v-model="addprod.info"></mavon-editor>
</el-form-item>
// 图片上传并替换地址
// 绑定@imgAdd event
$imgAdd (pos, $file) {
// 第一步.将图片上传到服务器.
let formdata = new FormData()
formdata.append('file', $file)
// let uploadparams = {
// data: formdata,
// headers: { 'Content-Type': 'multipart/form-data' }
// }
// console.log('pos: ' + pos, formdata, $file)
UploadFile(formdata)
.then(url => {
// console.log(url)
console.log(this.addprod.info)
// 第二步.将返回的url替换到文本原位置![...](./0) -> ![...](url)
this.$refs.md.$img2Url(pos, url.data)
})
}
// 上传图片接口
export const UploadFile = params => {
return axios({
url: base + '/upload',
method: 'post',
headers: { 'Content-Type': 'multipart/form-data' },
data: params
})
}
服务端代码
const {User, Product} = require('../models/model')
const formidable = require('formidable')
const form = new formidable.IncomingForm()
const path = require('path')
const fs = require('fs')
module.exports = {
// 注册
regin: async (req, res, next) => {
const newuser = new User(req.body)
const adduser = await newuser.save()
res.status(200).send({
adduser: adduser
})
},
// 登录
login: async (req, res, next) => {
const user = await User.findOne(req.query)
res.status(200).json({
code: 200,
msg: '登录成功',
user: user
})
},
// 上传图片
upload: (req, res, next) => {
//上传文件的保存路径
form.uploadDir = path.dirname('./upload/upload/')
//保存扩展名
form.keepExtensions = true
//上传文件的最大大小
form.maxFieldsSize = 20 * 1024 * 1024
form.parse(req, (err, fields, files) => {
// 项目未打包时使用
const imagepath = 'http://localhost:8088/' + path.normalize(files.file.path)
// 项目打包到server之后使用
// const imagepath = path.normalize(files.file.path)
res.status(200).send(imagepath)
// return next()
})
},
// 发送文件
sendfile: (req, res, next) => {
// console.log(req.params)
const curfile = path.resolve(__dirname,'../upload/' + req.params.imagename)
// console.log(curfile)
res.status(200).sendFile(curfile)
// return next()
}
}
查了好多资料,大概知道这个错误是因为 我在发了一次http响应头之后又发了一次响应头,程序做出了重复响应,但我检查了半天也没发现哪里重复谢了多个res.xxx啊,其它写return的办法也试过,还是没解决。
同时前端会有一个跨域代理的错误
[HPM] Error occurred while trying to proxy request //upload from localhost:8080 to http://localhost:8088 (ECONNRESET) (https://nodejs.org/api/errors...
_common_system_errors)
为了测试是否与跨域代理有关系,我将项目打包放到服务端测试,发现还是一样的错误,再次求助各位帮忙看看解决,先谢过了!!
首先,解决问题
遇到类似问题,官方文档往往是最好的解答。试下把你的代码改成下面这样,唯一的不同,就是把
form
的实例化挪动动upload
里。官方文档在 这里,仔细看两眼就会发现你的代码跟它的差别。
其次,探究问题根源
如果好奇问题出在哪里,可以看下 formidable 的源码,
incoming_form.js
。因为你所有的
parse
操作都是在同一个form
实例上进行,因此,this.on('end')
会被调用多次。end
事件的回调有两个,cb1、cb2。文件上传成功,cb1首先被调用,然后就悲剧了