【问题标题】:Download file from URL and upload it to AWS S3 without saving into memory using AWS SDK for Java, version 2使用适用于 Java 的 AWS 开发工具包版本 2 从 URL 下载文件并将其上传到 AWS S3,而无需保存到内存中
【发布时间】:2021-06-15 04:37:57
【问题描述】:

我正在编写一个代码,该代码将从 URL 下载文件并将其上传到 S3,但我不希望它临时存储在文件或内存中,我正在通过“InputStream”下载,但 AWS s3 需要该文件我从“InputStream”中没有的大小还有其他方法。 I found the this discussion on same topic using 'Node.js'


我在 inputStream 中获取文件的代码


HttpClient client = HttpClient.newBuilder().build();
URI uri = URI.create("{myUrl}");
HttpRequest request = HttpRequest.newBuilder().uri(uri).build();
InputStream is = client.send(request, HttpResponse.BodyHandlers.ofInputStream()).body();

我尝试插入 S3 的代码,但我没有 content_length


S3Client s3Client = S3Client.builder().build();
PutObjectRequest objectRequest = PutObjectRequest.builder()
                            .bucket(BUCKET_NAME)
                            .key(KEY)
                            .build();

PutObjectResponse por = s3Client.putObject(objectRequest, RequestBody.fromInputStream(is,content_length));

【问题讨论】:

  • 我不知道是否相关,但是使用'S3AsyncClient' for 'AsyncRequestBody' 没有方法'fromInputStream()',我没有找到原因?

标签: java amazon-web-services amazon-s3 aws-sdk inputstream


【解决方案1】:

“我尝试插入 S3 的代码,但我没有 content_length”

要绕过必须有内容长度的问题 - 您可以使用 btye[],而不是使用需要内容长度的 InputStream,如此处所述。

https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/sync/RequestBody.html#fromBytes-byte:A-

获取字节数组取决于您正在构建的应用程序。例如,在某些应用程序中,字节数组可以从发布到 Web 应用程序的文件中创建。其他应用程序,可以从在特定位置读取的文件创建字节数组。这里的重点是您的应用必须以某种方式获取字节数组并使用该数据将内容上传到 S3 存储桶。

如果您的应用有一个 InputStream(根据您的线程描述,您似乎已经拥有),请使用 Java 逻辑将其转换为 byte[]。一旦有了 byte[],就可以调用 putObject,如下所示。

public String putObject(byte[] data, String bucketName, String objectKey) {

        s3 = getClient();

        try {
            //Put a file into the bucket
            PutObjectResponse response = s3.putObject(PutObjectRequest.builder()
                            .bucket(bucketName)
                            .key(objectKey)
                            .build(),
                    RequestBody.fromBytes(data));

            return response.eTag();

        } catch (S3Exception e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
        return "";
    }

【讨论】:

  • 但是我将如何将数据放入'byte []',因为我必须将整个下载的文件加载到内存中,这是我不想要的。
  • 你想用什么魔法来转移byte[]???不可能!!!您是驱动程序,您的步骤只是将bytes[](此时在内存中)传输到 S3 库的输入流...
【解决方案2】:

你有几个选择。

最简单的方法是保留client.send() 中的HttpResponse,并从中获取Content-Length 标头。您还应该寻找像 Content-Type 这样的标头,并将它们作为元数据存储在 S3 对象上。

不能保证在所有情况下都有效:某些服务器不提供Content-Length。在这种情况下,您需要创建一个multipart upload 来发送文件。执行此操作时,您在内存中缓冲相对较小的块(最小 5 MB),但最多可以上传 10,000 个块。您必须完成或中止上传,或者将您的存储桶配置为在一段时间后删除未完成的上传;否则,您需要为不完整的上传付费。

第三种选择是使用 V1 SDK,它为您提供TransferManager。它为您处理多部分上传,并使用多个线程来提高带宽。但它还没有在 V2 中实现。

【讨论】:

    猜你喜欢
    • 2014-04-06
    • 2012-06-05
    • 2020-10-29
    • 1970-01-01
    • 2017-12-15
    • 2012-11-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    相关资源
    最近更新 更多