使用Axios上传Base64时Promise对象传递异常问题排查
问题:Base64转换后后端收到Promise对象而非实际字符串
我找到的Base64转换函数都依赖Promise,于是写了一个返回Promise的getBase64函数,用await等待转换结果后返回。但提交表单时,后端收到的文件内容还是Promise对象,明显await没起作用。
代码示例
getBase64: async (file) => { let data = await new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => resolve(reader.result); reader.onerror = (error) => reject(error); }) return data }, submitHistoricalPreprint() { if (this.$refs['AddHistoricalPreprintForm'].validate()) { let form = new FormData() this.historicalPreprintDocs.forEach((round, index) => { form.append(`data[${index}].ppid`, this.selectPPID.PPID) form.append(`data[${index}].round`, round.round) if (round.preprint) { form.append(`data[${index}].preprint.fileName`, round.preprint.name) form.append(`data[${index}].preprint.content`, this.getBase64(round.preprint)) } else { form.append(`data[${index}].preprint`, null) } round.supportingDocumentation ? round.supportingDocumentation.forEach((file, index2) => { form.append(`data[${index}].supportingDocumentation[${index2}].fileName`, file.name) form.append(`data[${index}].supportingDocumentation[${index2}].content`, this.getBase64(file)) }) : form.append(`data[${index}].supportingDocumentation`, null) if (round.oactQuestions) { form.append(`data[${index}].oactQuestions.fileName`, round.oactQuestions.name) form.append(`data[${index}].oactQuestions.content`, this.getBase64(round.oactQuestions)) } else { form.append(`data[${index}].oactQuestions`, null) } round.cmcsResponses ? round.cmcsResponses.forEach((file,index2) => { form.append(`data[${index}].cmcsResponses[${index2}].fileName`, file.name) form.append(`data[${index}].cmcsResponses[${index2}].content`, this.getBase64(file)) }) : form.append(`data[${index}].cmcsResponses`, null) if (round.stateResponses) { form.append(`data[${index}].stateResponses.fileName`, round.stateResponses.name) form.append(`data[${index}].stateResponses.content`, this.getBase64(round.stateResponses)) } else { form.append(`data[${index}].stateResponses`, null) } if (round.approvalLetter) { form.append(`data[${index}].approvalLetter.fileName`, round.approvalLetter.name) form.append(`data[${index}].approvalLetter.content`, this.getBase64(round.approvalLetter)) } else { form.append(`data[${index}].approvalLetter`, null) } }) axios({ method: 'post', url: window.location.origin + '/Preprint/UploadHistoricalReview', data: form, headers: { 'Content-Type': 'multipart/form-data', "RequestVerificationToken": document.forms[0].querySelector('input[name="__RequestVerificationToken"]').value, } }).then(response => { this.historicalPreprintDocs = [{ "round": 1, "preprint": null, "supportingDocumentation": [], "oactQuestions": null, "cmcsResponses": [], "stateResponses": null, "approvalLetter": null, }] this.$refs['AddHistoricalPreprintForm'].reset(); }).catch(error => { if (error.response.status == 401 || error.response.status == 402 || error.response.status == 403) { window.location.href = error.response.headers.expiredtokenredirecturi } console.log(error.response.data.error); }); } },
问题原因
核心问题有两个:
submitHistoricalPreprint不是异步函数,无法在内部使用await等待getBase64的转换结果forEach循环不支持异步回调阻塞,直接调用this.getBase64(file)会直接返回Promise对象,而非解析后的Base64字符串,导致FormData中存储的是Promise而非实际内容
解决方案
- 将
submitHistoricalPreprint声明为async函数 - 把
forEach替换为for...of循环,支持在循环内部使用await等待异步操作完成 - 所有调用
this.getBase64(file)的位置都添加await,确保拿到实际的Base64字符串
修改后的代码示例
getBase64: async (file) => { // 简化函数,直接返回Promise即可 return new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => resolve(reader.result); reader.onerror = (error) => reject(error); }) }, async submitHistoricalPreprint() { if (this.$refs['AddHistoricalPreprintForm'].validate()) { let form = new FormData() // 用for...of替代forEach,支持async/await for (const [index, round] of this.historicalPreprintDocs.entries()) { form.append(`data[${index}].ppid`, this.selectPPID.PPID) form.append(`data[${index}].round`, round.round) if (round.preprint) { form.append(`data[${index}].preprint.fileName`, round.preprint.name) // 等待Base64转换完成 const preprintBase64 = await this.getBase64(round.preprint) form.append(`data[${index}].preprint.content`, preprintBase64) } else { form.append(`data[${index}].preprint`, null) } if (round.supportingDocumentation && round.supportingDocumentation.length > 0) { // 处理支持文档数组 for (const [index2, file] of round.supportingDocumentation.entries()) { form.append(`data[${index}].supportingDocumentation[${index2}].fileName`, file.name) const docBase64 = await this.getBase64(file) form.append(`data[${index}].supportingDocumentation[${index2}].content`, docBase64) } } else { form.append(`data[${index}].supportingDocumentation`, null) } if (round.oactQuestions) { form.append(`data[${index}].oactQuestions.fileName`, round.oactQuestions.name) const oactBase64 = await this.getBase64(round.oactQuestions) form.append(`data[${index}].oactQuestions.content`, oactBase64) } else { form.append(`data[${index}].oactQuestions`, null) } if (round.cmcsResponses && round.cmcsResponses.length > 0) { for (const [index2, file] of round.cmcsResponses.entries()) { form.append(`data[${index}].cmcsResponses[${index2}].fileName`, file.name) const cmcsBase64 = await this.getBase64(file) form.append(`data[${index}].cmcsResponses[${index2}].content`, cmcsBase64) } } else { form.append(`data[${index}].cmcsResponses`, null) } if (round.stateResponses) { form.append(`data[${index}].stateResponses.fileName`, round.stateResponses.name) const stateBase64 = await this.getBase64(round.stateResponses) form.append(`data[${index}].stateResponses.content`, stateBase64) } else { form.append(`data[${index}].stateResponses`, null) } if (round.approvalLetter) { form.append(`data[${index}].approvalLetter.fileName`, round.approvalLetter.name) const approvalBase64 = await this.getBase64(round.approvalLetter) form.append(`data[${index}].approvalLetter.content`, approvalBase64) } else { form.append(`data[${index}].approvalLetter`, null) } } try { // 用await替代then/catch,代码更简洁 const response = await axios({ method: 'post', url: window.location.origin + '/Preprint/UploadHistoricalReview', data: form, headers: { 'Content-Type': 'multipart/form-data', "RequestVerificationToken": document.forms[0].querySelector('input[name="__RequestVerificationToken"]').value, } }) this.historicalPreprintDocs = [{ "round": 1, "preprint": null, "supportingDocumentation": [], "oactQuestions": null, "cmcsResponses": [], "stateResponses": null, "approvalLetter": null, }] this.$refs['AddHistoricalPreprintForm'].reset(); } catch (error) { if (error.response.status == 401 || error.response.status == 402 || error.response.status == 403) { window.location.href = error.response.headers.expiredtokenredirecturi } console.log(error.response.data.error); } } },
内容的提问来源于stack exchange,提问作者Qiuzman
相关产品推荐
相关产品推荐

