学无止境,气有浩然
文章目录
前言
工作里做的一个小工具,axios
传参,使用FormData
传参到后端,没有办法映射除字段值,但是从控制台看,传的字段值都是正确的,当然开始是因为简单没有将axios
抽调公共组件,由于抽调出来之后开始报这个错误,那么很明显就是这个问题导致了。
展示问题代码
-
请求部分
handleFileUpload(file) {
const formData = new FormData()
if (file) {
formData.append('file', file.file)
}
formData.append('name', this.form.name)
formData.append('num', this.form.num)
formData.append('env', this.form.env)
formData.append('nameGenMethod', this.form.nameGenMethod)
request.post('/home/test', formData, {
responseType: 'blob',
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(response => {
this.filedownload(response)
this.message({ message: 'handle success', type: 'success' }) }).catch(error => { const decoder = new TextDecoder('utf-8'); this.message({
message: decoder.decode(error.response.data),
type: 'error'
})
})
},
filedownload (res) {
const filename = res.headers['content-disposition']
// const blob = new Blob([ iconv.decode(res.data, 'GBK')])
const blob = new Blob([ res.data])
var downloadElement = document.createElement('a')
var href = window.URL.createObjectURL(blob)
downloadElement.href = href
let finalfilename = filename.split('filename=')[1]
if (finalfilename.startsWith('"')) {
finalfilename = finalfilename.substring(1)
}
if (finalfilename.endsWith('"')) {
finalfilename = finalfilename.substring(0, finalfilename.length - 1)
}
downloadElement.download = decodeURIComponent(finalfilename)
document.body.appendChild(downloadElement)
downloadElement.click()
document.body.removeChild(downloadElement)
window.URL.revokeObjectURL(href)
}
} -
公共部分
import axios from 'axios'
import { Notification } from 'element-ui'// 创建axios实例
const service = axios.create({
baseURL: process.env.NODE_ENV === 'production' ? process.env.VUE_APP_BASE_API : '/', // api 的 base_url
timeout: 3000000 // 请求超时时间
})function getToken () {
let accessToken = sessionStorage.getItem("access_token")
if (accessToken) {
return 'Bearer ' + accessToken
}
return false
}
// request拦截器
service.interceptors.request.use(
config => {
if (getToken()) {
config.headers.Authorization = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
config.headers['Content-Type'] = 'application/json'
return config
},
error => {
Promise.reject(error)
}
)// response 拦截器
service.interceptors.response.use(
response => {
if (response.data instanceof Blob) {
return response
}
return response.data
},
error => {
if (error.toString().indexOf('Error: timeout') !== -1) {
Notification.error({
title: '网络请求超时',
duration: 300000
})
return Promise.reject(error)
}
// 兼容blob下载出错json提示
if (error.response.data instanceof Blob) {
error.response.data.text().then(res => {
Notification.error({
title: res,
duration: 3000
})
})
} else {
let code = 0
try {
code = error.response.status
} catch (e) {
if (error.toString().indexOf('Error: timeout') !== -1) {
Notification.error({
title: '网络请求超时',
duration: 3000
})
return Promise.reject(error)
}
}
if (code) {
if (code === 401) {
Notification.warning({
title: '未认证',
duration: 3000
})
sessionStorage.removeItem("access_token")
} else if (code === 403) {
Notification.warning({
title: '未认证',
duration: 3000
})
sessionStorage.removeItem("access_token")
} else if (code === 500) {
const errorMsg = error.response.data
if (errorMsg !== undefined) {
Notification.error({
title: errorMsg,
duration: 3000
})
} else {
Notification.error({
title: '未知错误',
duration: 3000
})
}
} else {
const errorMsg = error.response.data.message
if (errorMsg !== undefined) {
Notification.error({
title: errorMsg,
duration: 5000
})
} else {
Notification.error({
title: '未知错误',
duration: 3000
})
}
}
} else {
Notification.error({
title: '远程服务器断开连接',
duration: 3000
})
}
}
return Promise.reject(error)
}
)
export default service
因为项目可能会传文件,虽然不是必选项,但是可以通用,所以
axios
传输的时候可以使用multipart/form-data
的请求头。
问题
在抽取公共请求代码的时候,重新设置了请求头为application/json
,就导致使用js
提供的FormData
无法解析成为json
,导致接收不到请求。
解决
就是判断一下请求里面是否设置了请求头就好了。
java
if (!config.headers['Content-Type']) {
config.headers['Content-Type'] = 'application/json'
}