使用AWS SDK for Java 2版本,从URL下载文件并将其上传到AWS S3而不保存在内存中

5
我正在编写一段代码,用于从URL下载文件并将其上传到S3,但我不希望它被暂时存储在文件或内存中,我是通过'InputStream'进行下载的,但AWS s3需要文件大小,而我从'InputStream'中没有这个数据,是否还有其他方法。 我在同一主题上发现了使用'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'处理'AsyncRequestBody'时没有'fromInputStream()'方法,我不知道为什么? - Ketan Chaudhari
2个回答

1

"我试图将代码插入到S3中,但我没有content_length"

为了避免需要content length的限制 - 你可以使用一个byte[]来代替使用需要content length的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 "";
    }

1
但是我该如何将数据加载到“byte []”中呢?为此,我必须将整个下载的文件加载到内存中,而我不想这样做。 - Ketan Chaudhari
你想用什么魔法来传输 byte[]???没有办法!!!你是驱动程序,你的步骤只是将 bytes[](此时在内存中)传输到 S3 库的输入流中... - Marcello DeSales

1

你有几个选择。

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

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

第三种选择是使用V1 SDK,该SDK提供了TransferManager。它会为你处理多部分上传,并使用多个线程来提高带宽利用率。但它仍然没有为V2实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接