NodeJS/VueJS从Amazon S3下载PDF遇网络错误及文件损坏求助
NodeJS/VueJS从S3下载PDF:错误原因与解决方法
问题原因分析
1. Data URI方式触发「Network Error」
Chrome浏览器对动态创建a标签下载Data URI的行为存在隐性安全限制,即使文件体积很小,也可能因浏览器策略拦截触发网络错误提示,和文件大小无关。
2. Blob方式导致文件损坏
服务器返回的是PDF文件的base64编码字符串,但客户端直接将该字符串作为内容创建Blob,相当于把base64文本本身当作二进制数据保存,而非解码还原成原始的PDF二进制字节流,最终下载的文件实际是base64文本内容,自然无法被PDF阅读器识别。
正确解决方法
提供两种可行方案,推荐第二种(直接传输二进制流),更高效且避免编码转换问题。
方案一:修正客户端base64解码逻辑
保持现有服务器端代码不变,客户端收到base64字符串后先解码为原始二进制数据,再创建Blob:
getPdfContent: async function (filename) { const resp = await AxiosService.getPdf(filename) // 将base64字符串解码为Uint8Array格式的二进制数据 const binaryString = atob(resp.data) const byteArray = new Uint8Array(binaryString.length) for (let i = 0; i < binaryString.length; i++) { byteArray[i] = binaryString.charCodeAt(i) } const pdfBlob = new Blob([byteArray], { type: 'application/pdf' }) const downloadUrl = window.URL.createObjectURL(pdfBlob) const link = document.createElement('a') link.href = downloadUrl link.download = filename link.click() // 释放URL对象,避免内存泄漏 window.URL.revokeObjectURL(downloadUrl) }
方案二:直接传输二进制流(推荐)
跳过base64编码转换,服务器直接返回S3获取的二进制数据,客户端以Blob形式接收,效率更高且无编码错误风险。
服务器端修改:
const filename = 'lets_go_to_the_snackbar.pdf'; const s3 = new AWS.S3(some access parameters); const params = { Bucket: do_not_kick_this_bucket, Key: `yellowbrickroad/${filename}` } try { const data = await s3.getObject(params).promise(); // 设置正确的响应头,告知浏览器文件类型与下载属性 res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); // 直接发送原始二进制数据 res.send(data.Body); } catch (err) { console.log(err); res.status(500).send('文件下载失败'); }
客户端修改:
首先确保axios请求时指定responseType: 'blob',再处理下载:
// 调整AxiosService的getPdf方法 getPdf: function(filename) { return axios.get('/your-api-endpoint', { params: { filename }, responseType: 'blob' // 关键配置:接收Blob类型响应 }); } // 下载方法实现 getPdfContent: async function (filename) { const resp = await AxiosService.getPdf(filename) const downloadUrl = window.URL.createObjectURL(resp.data) const link = document.createElement('a') link.href = downloadUrl link.download = filename link.click() window.URL.revokeObjectURL(downloadUrl) }
内容的提问来源于stack exchange,提问作者TheLoneliestMonk
相关产品推荐
相关产品推荐

