请求头中传递错误信息
1.Java代码中添加
response.setHeader("Access-Control-Allow-Origin", "*");// 允许的请求方法(根据实际接口方法设置,如 GET/POST)response.setHeader("Access-Control-Allow-Methods", "POST");// 允许的请求头(* 表示允许所有)response.setHeader("Access-Control-Allow-Headers", "*");// 关键:暴露自定义错误头,允许前端读取 X-Error-Code 和 X-Error-Messageresponse.setHeader("Access-Control-Expose-Headers", "X-Error-Code,X-Error-Message");// 允许携带 Cookie(如需跨域传递身份信息,设为 true)response.setHeader("Access-Control-Allow-Credentials", "true");// 2. 设置错误信息头response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 500 状态码response.setHeader("X-Error-Code", "500");String encodedErrorMsg = URLEncoder.encode(errorMsg, StandardCharsets.UTF_8.name());response.setHeader("X-Error-Message", encodedErrorMsg);
- 前端解析
/*** 批量下载报告* @param data 包含itemsCode参数的对象*/
export const batchDownload = async (data: { itemsCode: string }): Promise<Blob> => {const result: AxiosResponse<Blob> = await axios({method: 'post',url: `/api/job/taskCheckReport/batchDownload`,params: data,responseType: 'blob',})console.log(result);if (isCustomAxiosError(result)) {return result as unknown as Blob}// 检查Blob响应是否包含错误信息// 如果后端返回错误,Blob可能包含JSON格式的错误信息const blob = result.dataif (blob.type === 'application/json') {// 如果是JSON类型,说明后端返回了错误信息const text = await blob.text()try {const errorData = JSON.parse(text)// 如果handleHttpResponse返回false(表示有错误),抛出错误if (!handleHttpResponse(errorData)) {throw new Error(errorData.msg || '下载失败')}} catch {// JSON解析失败,说明不是错误信息,返回原始blobreturn new Blob([text], { type: 'application/json' })}}// 对于正常的文件流,显示成功提示并返回blob对象ElMessage.success('批量下载成功')return blob
}
// 直接完成(暂未使用)
// const handleComplete = () => {
// console.log('直接完成')
// }
// 批量下载
const handleBatchDownload = async () => {console.log('批量下载')const selects = tableRef.value?.getSelectionRows()if (selects == null || selects.length < 0) {ElMessage.error('请选择要下载的报告')return}try {// 显示加载提示const loading = ElMessage.info({message: '正在准备批量下载...',duration: 0})// 提取报告编号,优先使用 itemscode 字段const reportCodes = selects.map((item: any) => item.itemscode || item.itemsCodeX)// 检查是否有有效的报告编号if (reportCodes.length === 0 || reportCodes.some((code: string) => !code)) {loading.close()ElMessage.error('选中的报告中存在无效的报告编号,无法下载')return}// 将报告编号用逗号连接成字符串const itemsCodeString = reportCodes.join(',')console.log('批量下载参数:', { itemsCode: itemsCodeString })// 调用批量下载接口const req = useRequest<any>()const response = await req(batchDownload.bind(null, { itemsCode: itemsCodeString }))// 关闭加载提示loading.close()// 检查响应是否为有效的Blob对象if (!response || !(response instanceof Blob)) {console.error('批量下载接口返回无效的响应:', response)// 后端接口会自动返回错误提示,这里不需要额外处理return}// 关键改进:检查响应是否包含错误信息// 如果响应类型是 'application/json',说明后端返回了错误信息而不是文件流if (response.type === 'application/json') {console.log('检测到错误响应,停止下载操作')// 尝试读取错误信息并显示给用户try {const errorText = await response.text()const errorData = JSON.parse(errorText)console.error('批量下载接口返回错误信息:', errorData)// 错误信息已经在 handleHttpResponse 中处理过,这里不需要重复提示return} catch (parseError) {console.error('解析错误响应失败:', parseError)// 如果解析失败,也不应该继续下载return}}// 只有响应是有效的文件流时才继续下载// 创建下载链接const url = window.URL.createObjectURL(response)const link = document.createElement('a')link.href = urllink.download = `批量报告下载-${moment().format('YYYYMMDDhhmmss')}.zip`link.click()window.URL.revokeObjectURL(url)} catch (error: any) {// 关闭加载提示(如果存在)ElMessage.closeAll()ElMessage.error(decodeURIComponent(error.response.headers['x-error-message']))}
}
ElMessage.error(decodeURIComponent(error.response.headers['x-error-message']))
