最近碰到个需求如下:
表单里既有普通文本字段,又有上传文件,且是多个不同字段(不是一个字段多个文件);
当时后端只给了一个接口:
思路是先var formdata=new formdata(),再formdata.append('xx',xxx);再axios.post('url',formdata);
实际写的时候碰到了一些问题,很多axios都会在使用前进行封装一下,加上拦截器,我用vue-element-admin作为后台模板,里面的axios也设置了拦截器,拦截器里面会对传输的参数进行过滤,例如这些代码:
if(config.data && !config.data.param){
config.data = qs.stringify(config.data);
}
这就导致,发送请求的时候请求头里面content-type都不是multiple/form-data 而是application/x-www-form-urlencoded;
后端根本接收不到数据,我又试了下在axios里面加上headers: {'Content-Type': 'multipart/form-data'}仍然没有传值到后台;
后来百度了之后,查到资料说需要建一个纯净的axios,再通过这个纯净的axios发送请求,于是就成功了,核心代码如下:
import myaxios from "axios"
export function updateWx(param) {
return myaxios.post(url_base+'/wechatConfig/update',param).then((res)=>{
return res
})
}
<el-form-item label="微信公钥证书文件" prop="publicKeyFile">
<el-upload
class="upload-demo"
ref="upload"
accept=".pem"
:multiple="false"
:limit="1"
:action="this.url"
name="publicKeyFile"
:file-list="fileList"
:before-upload="beforeupload"
:data="this.temp"
:auto-upload="false">
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<div slot="tip" class="el-upload__tip">只能上传pem格式文件</div>
</el-upload>
</el-form-item>
<el-form-item label="微信私钥证书文件" prop="privateKeyFile">
<el-upload
class="upload-demo"
ref="upload2"
accept=".pem"
:multiple="false"
:limit="1"
:action="this.url"
name="privateKeyFile"
:file-list="fileList"
:before-upload="beforeupload1"
:data="this.temp"
:auto-upload="false">
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<div slot="tip" class="el-upload__tip">只能上传pem格式文件</div>
</el-upload>
</el-form-item>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">
{{ $t('table.cancel') }}
</el-button>
<el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
{{ $t('table.confirm') }}
</el-button>
</div>
data() {
return {
uploadForm: new FormData(),
fileList :[],
list: [],
}
}
beforeupload(file){
this.uploadForm.append("publicKeyFile",file)
},
beforeupload1(file){
this.uploadForm.append("privateKeyFile",file)
},
updateData() {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
this.uploadForm.append('businessAccount', this.temp.businessAccount)
this.uploadForm.append('token', this.temp.token)
this.uploadForm.append('payKey', this.temp.payKey)
this.uploadForm.append('mchId', this.temp.mchId)
var len=this.$refs['upload'].$children[0].fileList.length
var len2=this.$refs['upload2'].$children[0].fileList.length
if(len){
this.$refs.upload.submit() // 提交时触发了before-upload函数
}
if(len2){
this.$refs.upload2.submit()
}
updateWx(this.uploadForm).then(() => {
this.dialogFormVisible = false
this.$notify({
title: '成功',
message: '更新成功',
type: 'success',
duration: 2000
})
//重新加载
this.$router.replace({
path: "/redirect" + '/pay/wxpay',
}).then(() => {
setTimeout(() => {
this.pulse = false;
}, 1000);
}).catch(() => {});
})
}
})
},
后记:文件上传,后端应该是会封装一个文件上传的基础方法,然后需要上传文件的时候在一个方法里面调用这个基础方法就好了,这样就可以给出一个专门上传文件的接口,前端请求这个接口后,得到后端返回的文件存储地址,表单提交的时候把这个地址字符串传给后台,这样做前端可以写的优雅,后台也可以提高内聚