最近碰到個需求如下:
表單裏既有普通文本字段,又有上傳文件,且是多個不同字段(不是一個字段多個文件);
當時後端只給了一個接口:
思路是先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(() => {});
})
}
})
},
後記:文件上傳,後端應該是會封裝一個文件上傳的基礎方法,然後需要上傳文件的時候在一個方法裏面調用這個基礎方法就好了,這樣就可以給出一個專門上傳文件的接口,前端請求這個接口後,得到後端返回的文件存儲地址,表單提交的時候把這個地址字符串傳給後臺,這樣做前端可以寫的優雅,後臺也可以提高內聚