使用适用于 Java 的 AWS SDK,版本 2 从 URL 下载文件并将其上传到 AWS S3 而无需保存到内存中

Download file from URL and upload it to AWS S3 without saving into memory using AWS SDK for Java, version 2

我正在编写一个代码,将从 URL 下载文件并将其上传到 S3,但我不希望它临时存储在文件或内存中,我正在通过 [=25 下载=] 但 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));

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

为了避免必须有内容长度 - 而不是使用确实需要内容长度的 InputStream,您可以使用 btye[],如此处所述。

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

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

如果您的应用程序有一个 InputStream(根据您的线程描述,您似乎有一个 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 "";
    }

你有几个选择。

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

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

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