You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Lambda生成的S3预签名URL实现前端直接下载存储桶文件

问题根因

你当前的代码逻辑是直接把API Gateway返回的Lambda响应内容(也就是包裹着预签名URL的JSON文本)封装成Blob触发下载,最终下载到的自然是存着URL字符串的JSON文件,根本没有访问S3上的实际目标文件。

修改方案

核心调整逻辑是先解析接口返回内容拿到真实的S3预签名URL,再基于这个URL触发目标文件下载,有两种可直接复用的实现方式:

  • 方式一:直接指向预签名URL触发下载(代码最简,要求S3存储桶已配置当前站点的跨域访问规则)
  • 方式二:二次请求预签名URL拿到文件流后转Blob触发下载(兼容性最好,可强制触发下载避免浏览器预览文件,无跨域问题)

可直接替换的代码

方式一(最简实现)

fetch("https://********.execute-api.us-east-1.amazonaws.com/test", requestOptions)
.then(res => res.json())
.then(presignedUrl => {
  // 去除接口返回可能包裹URL的多余引号
  const s3FileUrl = presignedUrl.replace(/^"|"$/g, '')
  const downloadLink = document.createElement("a")
  downloadLink.href = s3FileUrl
  // 替换为你需要的实际保存文件名,要带上对应后缀,比如demo.pdf、resource.zip
  downloadLink.download = "实际目标文件名"
  downloadLink.style.display = "none"
  document.body.appendChild(downloadLink)
  downloadLink.click()
  document.body.removeChild(downloadLink)
})

方式二(兼容最优实现)

如果方式一出现跨域报错,或者点击后文件被浏览器直接打开预览而非下载,用这个版本:

fetch("https://********.execute-api.us-east-1.amazonaws.com/test", requestOptions)
.then(res => res.json())
.then(async presignedUrl => {
  const s3FileUrl = presignedUrl.replace(/^"|"$/g, '')
  // 请求S3拿到真实文件流
  const fileResponse = await fetch(s3FileUrl)
  const fileBlob = await fileResponse.blob()
  const downloadLink = document.createElement("a")
  const objectUrl = window.URL.createObjectURL(fileBlob)
  downloadLink.href = objectUrl
  downloadLink.download = "实际目标文件名"
  downloadLink.style.display = "none"
  document.body.appendChild(downloadLink)
  downloadLink.click()
  // 释放内存,移除临时节点
  window.URL.revokeObjectURL(objectUrl)
  document.body.removeChild(downloadLink)
})
注意事项
  • a.download属性的文件名必须和目标文件格式匹配,否则下载后的文件会出现格式错误无法打开的问题
  • 如果Lambda返回的预签名URL本身已经在S3签名里指定了response-content-disposition=attachment响应头,方式一也会强制触发下载,不会出现预览问题

内容的提问来源于stack exchange,提问作者user14677532

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 12:03:21