Lambda+APIGateway实现S3 PDF下载 Axios调用Chrome报网络错误
问题背景
- 已完成Lambda + API Gateway接口搭建,可实现从S3存储下载PDF文件,Postman测试下载功能正常
- 前端使用Node.js生态的Axios库调用该接口时,Chrome浏览器提示「Failed - Network error」,无法正常保存下载文件
原有实现代码
const downloadSearchResult = async (params) => { console.log("download") const link = document.createElement("a"); var axios = require('axios'); var config = { method: 'get', url: `https://xxxxxxx.amazonaws.com/v1/xxx?file=${params.row.Filename}`, headers: { } }; axios(config) .then(function (response) { link.href = `data:application/pdf;base64,` + response.data; link.download = params.row.Filename; link.click(); console.log(JSON.stringify(response.data)); }) .catch(function (error) { console.log(error); }); }
异常表现
Chrome控制台可正常打印JSON.stringify(response.data)的接口返回内容,但触发a标签下载动作后文件无法保存,最终浏览器提示下载失败、网络错误。
故障原因
两个核心问题共同导致该异常:
- Axios默认响应类型为
json,没有配置二进制响应格式,接口返回的PDF二进制流被默认按文本/JSON格式转码,拼接成Base64 data URL的文件内容本身是损坏的 - Chrome浏览器对
data:协议的URL存在严格的大小限制,通常超过2MB的文件通过data URL触发下载时,会直接被拦截并抛出网络错误,和实际网络状态无关
修复方案
方案1(优先推荐,无文件大小限制)
不需要通过Axios请求接口拿文件内容,直接将a标签的href指向接口地址,触发原生下载即可,完全规避JS处理二进制、data URL大小限制的问题,代码最简兼容性最好:
const downloadSearchResult = (params) => { const link = document.createElement("a"); link.href = `https://xxxxxxx.amazonaws.com/v1/xxx?file=${encodeURIComponent(params.row.Filename)}`; link.download = params.row.Filename; // 兼容新标签页拦截逻辑 link.target = '_blank'; document.body.appendChild(link); link.click(); document.body.removeChild(link); }
注意:需要确保Lambda/API Gateway返回的响应头包含
Content-Disposition: attachment,如果接口已经配置该头,连download属性都可以省略。
方案2(必须经Axios处理请求的场景,比如需要带自定义鉴权头)
给Axios配置responseType: 'blob'指定响应为二进制Blob格式,拿到响应后通过URL.createObjectURL生成临时本地Blob地址赋值给a标签,不要使用Base64拼接data URL:
const axios = require('axios'); const downloadSearchResult = async (params) => { const config = { method: 'get', url: `https://xxxxxxx.amazonaws.com/v1/xxx?file=${encodeURIComponent(params.row.Filename)}`, // 核心配置:指定响应类型为二进制Blob responseType: 'blob', headers: { // 这里可以加自定义鉴权头等需要的请求头 } }; const response = await axios(config); // 生成Blob临时地址 const blobUrl = window.URL.createObjectURL(new Blob([response.data], {type: 'application/pdf'})); const link = document.createElement('a'); link.href = blobUrl; link.download = params.row.Filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); // 释放临时地址占用的内存 window.URL.revokeObjectURL(blobUrl); }
内容的提问来源于stack exchange,提问作者Rico
相关产品推荐
相关产品推荐

