【问题标题】:Download file from AWS lambda从 AWS lambda 下载文件
【发布时间】:2021-12-19 17:16:09
【问题描述】:
class DownloadFileHandler RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

  @Overrider
  public APIGatewayProxyResponseEvent handlerRequest(APIGatewayProxyRequestEvent event, Context context) {
      String fileName = event.getQueryStringParameters().get("fileName");
      AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);

      AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .withRegion(Regions.US_EAST_2).build();
      GetObjectRequest request = new GetObjectRequest(bucket, fileName);
      S3Object objectFile = s3Client.getObject(request);
      S3ObjectInputStream objectInputStream = objectFile.getObjectContent();
      // latest I was trying this
      byte [] fileBytes = new byte[0];

      try {
        fileBytes = objectInputStream.readAllBytes();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    Map<String, String> headers = new LinkedHashMap<>();
    headers.put("Content-Type", "application/json");
    headers.put("Accept", "application/octet-stream");
    headers.put("Content-Disposition", String.format(Locale.UK, "attachment; filename=%s", fileName));
    headers.put("Content-Length", String.valueOf(fileBytes.length));
    // I tried this 
    JSONObject response = new JSONObject();
    response.append("file", objectFile);

    APIGatewayProxyResponseEvent responseEvent = new APIGatewayProxyResponseEvent()
      .withHeaders(headers)
      .withStatusCode(200)
      .withIsBase64Encoded(true)
      .withBody(Base64.getEncoder().encodeToString(fileBytes));

    return responseEvent;
  }
}

在上面的代码中,我有 requestHandler 从 AWS S3 提取文件,它应该将其作为响应发送。我在上面进行了编码,您可以看到我尝试了至少两种非工作方法。我的意思是我可以将文件作为字符串发送,但我无法下载此文件。我得到的不是文件内容,而是

DIxMTc1NSAwMDAwMCBuDQowMDAwMjExODg3IDAwMDAwIG4NCjAwMDAyMTE5MTQgMDAwMDAgbg0KMDAwMDIxMjM5MiAwMDAwMCBuDQowMDAwMjE3NDQ3IDAwMDAwIG4NCjAwMDAyMTc1MTcgMDAwMDAgbg0KMDAwMDIxNzc4MiAwMDAwMCBuDQowMDAwMjE3ODYzIDAwMDAwIG4NCjAwMDAyMzExMDAgMDAwMDAgbg0KMDAwMDIzMTEyNyAwMDAwMCBuDQowMDAwMjMxNTA5IDAwMDAwIG4NCjAwMDAyMzY2MDkgMDAwMDAgbg0KMDAwMDIzNjY3OSAwMDAwMCBuDQowMDAwMjM2OTUwIDAwMDAwIG4NCjAwMDAyMzcwMzEgMDAwMDAgbg0KMDAwMDI0NTA4NSAwMDAwMCBuDQp0cmFpbGVyDQo8PC9TaXplIDE2Ny9Sb290IDE4IDAgUi9JbmZvIDE2IDAgUi9JRFs8RTdCRDQzNDY0Mzg0Q0M0OTU1QTVBQTNBRTIzMzQxNUI+PDM5RDcyRDQ5OEJGMzFFNDhCMEQ5QjkxODBFOEIzQzVFPl0vUHJldiAyMDI0MzA+Pg0Kc3RhcnR4cmVmDQoyNDk0NDgNCiUlRU9GDQo=%
[content cut out]

所以我认为那是文件。但是由于某种原因我无法下载它,因为当我保存这个文件时它无法打开,我收到file damaged etc.

这样的错误

如果能帮助我理解为什么这种方法不起作用,我将不胜感激?我在 AWS 文档中找不到任何关于 Java 的示例。其中大部分是关于 Python 或 JavaScript 的。似乎我不理解它们,因为我看到了类似的代码

response = {
  "statusCode" : 200,
  "body" : file
}

或类似的东西。对我来说,这意味着我必须将文件包装到 JSON 对象中,然后从我的处理程序方法中返回它。但这对我不起作用,因为我得到了你可以在上面看到的 2 sn-p 代码。请解释我做错了什么以及我不理解什么?

【问题讨论】:

  • 响应中的内容类型不会是 application/json。它将类似于 image/png 或 application/pdf,具体取决于您要发送其内容的文件。
  • 从AWS S3下载时,为什么标题说是从AWS Lambda下载?顺便说一句,看起来数据是 base64 编码的。
  • @DavidConrad AWS Lambda 函数位于 API Gateway 后面,它将对象从 S3 下载到 API 客户端。因此,API 客户端通过 API Gateway 从 Lambda 下载,而 Lambda 从 S3 下载,然后将文件内容发送到客户端。除此之外,这不是一个理想的解决方案(Lambda 函数可以简单地创建一个预签名的 URL 并将客户端 302 重定向到该 URL)。
  • jarmod 你的建议听起来很合理,但是如果我想发送不同类型的 pdf、docx 等呢?我在 aws doc 中读到,您应该始终从处理程序返回 JSON。

标签: java amazon-web-services file aws-lambda


【解决方案1】:

我不知道为什么这篇文章会得到减分,但无论如何。如果@jarmod 可以理解我想从 Lambda 下载,并且他可以为我指出为文件创建重定向请求的好方向,因为将对象从 S3 拉到 Lambda 然后再次通过 HTTP 发送它是错误的方法,我认为 post够清楚了。

这就是为什么我决定发布我的解决方案,感谢@jarmod 我可以想出。在这个处理程序中,我使用了S3Presinger,如果有人使用 AWS 网关创建 API 并希望下载存储在 AWS S3 上的文件,我认为这非常有用。

 public class DownloadFileHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
    @Override
    public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent event, Context context) {
        String bucket = "";

        try (InputStream input = new FileInputStream("./config/application.properties")) {
            Properties properties = new Properties();
            properties.load(input);

            bucket = properties.getProperty("bucket");
        } catch (IOException e) {
            e.printStackTrace();
        }

        String fileName = event.getQueryStringParameters().get("fileName");

        S3Presigner presigner = S3Presigner.builder().build();

        GetObjectPresignRequest presignRequest = GetObjectPresignRequest
                .builder()
                .signatureDuration(Duration.ofMinutes(10))
                .getObjectRequest(GetObjectRequest.builder().bucket(bucket).key(fileName).build())
                .build();

        PresignedGetObjectRequest presignedGetObjectRequest = presigner.presignGetObject(presignRequest);

        String presignedURL = presignedGetObjectRequest.url().toString();
        Map<String, String> headers = new LinkedHashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("Location", presignedURL);

        APIGatewayProxyResponseEvent responseEvent = new APIGatewayProxyResponseEvent()
                .withHeaders(headers)
                .withStatusCode(302);

        return responseEvent;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-10-15
    • 2017-05-25
    • 1970-01-01
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    • 2017-01-15
    相关资源
    最近更新 更多