繁体   English   中英

Nodejs - 使用预签名 url 从 s3 存储桶中下载文件

[英]Nodejs - React download file from s3 bucket using pre-signed url

我正在尝试制作一个 onClick 按钮以使用 pre-si.net url 从 S3 存储桶下载文件。当我收到我的 url 时出现问题。我想要一个自动重定向或类似的。 换句话说,我如何在取回我的签名 url 后下载下载文件?

这是我的文件清单

onClick 事件在下载按钮上。

redux行动

Redux 动作调用我的 nodejs 路由api 路由 nodejs

要求预签名 url 然后将其发送到我的 redux reducer。

现在在我的前端页面中,我得到了我的链接,但我想要一个自动重定向来开始文件下载。 组件的一部分

希望我的第一篇文章不会太乱。

我通过redux动作解决了我的问题。 一键式调用我的操作,操作者将返回我的预签名URL,然后自动单击链接。 当我将其上传到S3时,会触发具有原始文件名的下载事件。

 export const downDoc = (docId) => async dispatch => { const res = await axios({ url: 'myApiCall', method: 'GET', responseType: 'blob' }) .then((response) => { console.log(response) const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', `${docId.originalName}`); document.body.appendChild(link); link.click(); }); 

另一个答案直接进行 DOM 操作,创建一个 blob,它看起来好像在将整个文件发送给用户之前将整个文件缓冲在 memory 中,并且每次下载时都会创建一个新链接。 做的反应是:

const downloadFileRef = useRef<HTMLAnchorElement | null>(null);
const [downloadFileUrl, setDownloadFileUrl] = useState<string>();
const [downloadFileName, setDownloadFileName] = useState<string>();

const onLinkClick = (filename: string) => {
    axios.get("/presigned-url")
      .then((response: { url: string }) => {
        setDownloadFileUrl(response.url);
        setDownloadFileName(filename);
        downloadFileRef.current?.click();
      })
      .catch((err) => {
        console.log(err);
      });
  };

return (
<>
   <a onClick={() => onLinkClick("document.pdf")} aria-label="Download link">
       Download
   </a>
   <a
        href={downloadFileUrl}
        download={downloadFileName}
        className="hidden"
        ref={downloadFileRef}
   />
</>)

有关更多信息,请参见此处https://levelup.gitconnected.com/react-custom-hook-typescript-to-download-a-file-through-api-b766046db18a

我这样做的方式是不同的,并且具有能够在下载文件时看到下载进度的优势。 如果您正在下载一个大文件,那么当您立即看到反馈时,它会对用户体验产生影响。

我所做的是:

  1. 创建 S3 预签名 URL 时,我将content-disposition为“附件”
  2. 我使用锚元素来下载实际项目<a url='https://presigned-url' download>Download me</a>

其他人提到在 DOM 或 React 中模拟点击,但另一种选择是使用window.open() 您可以将 target 属性设置为_blank以打开选项卡,但您确实需要在单击事件中使用window.open()以防止弹出窗口阻止程序停止该功能。 这里有一些关于这个主题的很好的讨论。 我发现这是比模拟点击事件更好的解决方案。

这是一个示例(尽管可能需要更多,具体取决于您获取 signed_url 的方式)。

function downloadDocument() {
  const signedurlPromise = fetch("/signed_url")
  signedurlPromise.then((response) => {
      window.open(response.signed_url, "_blank");
  })
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM