【问题标题】:How can I initiate a download of an external Image (AWS Signed URL) on button press如何在按下按钮时启动外部图像(AWS 签名 URL)的下载
【发布时间】:2021-12-06 00:56:08
【问题描述】:

我正在尝试通过单击按钮(从客户端 Nextjs)从 s3 Presigned URL 下载图像。

这是背景:

我在后端使用 Golang。 前端的 Nextjs React 框架。

我首先尝试对后端进行 fetch 调用(因为我的 AWS 凭据存储只能通过后端访问)。然后后端将下载图像,以及 mime 类型“image/tiff”的下载流:

后端处理程序(批处理只是系统特定的):


// GetDownloadBatchFile handles GET requests to download the batch output file
func GetDownloadBatchFile(ctx *atreugo.RequestCtx) error {


    // Parse Batch ID
    batchIntfID := ctx.UserValue("batch_id")
    batchStrID, isStr := batchIntfID.(string)

    if !isStr {
        fmt.Println("User error. No batch ID provided")
    }

    batchIntID, err := strconv.Atoi(batchStrID)
    if err != nil {
        fmt.Println("User error. Invalid batch ID provided")
    }

    // Get Batch
    batch, err := models.GetBatchByID(batchIntID)
    if err != nil {
        fmt.Println("User Error. No batch associated with provided batch ID")
    }

    // Get Batch Setting
    batch.BatchSetting, err = models.GetBatchSettingByID(batch.BatchSettingID)
    if err != nil {
        fmt.Println("User Error. No batch setting associated with provided batch setting ID")
    }

    // Get signed url and download
    req, _ := util.AWSS3Svc.GetObjectRequest(&s3.GetObjectInput{
        Bucket: aws.String(batch.BatchSetting.AWSBucket),
        Key:    aws.String(batch.OutputFileKey),
    })

    // Get and Download Presigned URL
    URL, err := req.Presign(time.Hour * 1)
    if err != nil {
        fmt.Println("Whoops, failed to generate signed s3 preview link.")
    }

    resp, err := http.Get(URL)
    if err != nil {
        fmt.Println("System Error. Unable to download image file.")
    }

    batchImage,  err := tiff.Decode(resp.Body)
    if err != nil {
        fmt.Println(err)
    }


    ctx.Response.Header.Add("Content-Disposition", "attachment; filename=logo")
    ctx.Response.Header.SetContentType("image/tiff")
    err = tiff.Encode(ctx.Response.BodyWriter(), batchImage, &tiff.Options{Compression: tiff.Uncompressed}, uint32(batch.BatchSetting.DPI))
    if err != nil {
        return ctx.TextResponse(`ENCODE ERROR: ` + err.Error())
    }

    return nil
}

这通常会很好用,但问题是我的文件几乎是 1 GB!下载时间过长,然后响应超时。

我想我应该只是将预签名的 URL 发送到前端并从中下载,但我不知道如何从 URL 下载。

这里欢迎所有想法,以及有关如何在按钮按下时下载 url 的任何信息。谢谢!

【问题讨论】:

    标签: html reactjs amazon-web-services go next.js


    【解决方案1】:

    我不知道如何从 URL 下载

    我不清楚您目前是如何尝试在 Next.js 中执行此操作的,所以我会笼统地回答。

    一旦后端响应中可用,我将使用 Next/image 组件并将签名的 URL 提供给它的 src 属性。

    import Image from "next/image";
    import { useState } from "react";
    
    // If signedSrc is available, render the image
    const MyComponent = () => {
     const [signedSrc, signedSrcUpdate] = useState(null);
    
     return (
      <>
       <button onClick={async () => {
        // fetch signed image url
        const response = await fetch('https://your-api/signedimageurlendpoint';
        signedSrcUpdate(response.data);
       }}
       {signedSrc &&
        <Image
          src={signedSrc}
        />
       }
      </>
     )
    }
    

    【讨论】:

    • 啊,我明白你在这里做什么了。我实际上并没有尝试将图像放在页面上,而是将其下载给用户。我找到了一个可行的解决方案,并将在此处发布链接
    【解决方案2】:

    我找到了适合我的解决方案。我创建了一个函数并使用纯 javascript 从读取流中下载(我还让我的文件小得多,只有 90mb),并将按钮设置为在请求期间加载。这是一个漫长的等待,但它是可控的。这是如何在 js 中下载 readstream 的链接。

    How to download a ReadableStream on the browser that has been returned from fetch

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多