下载的 Amazon S3 文件不包含数据

Downloaded an Amazon S3 file doesn't contain data

我正在编写一项服务来下载 Amazon S3 存储桶中的文件,但我只收到一个空的 JSON 对象

视觉 | Axios -

downloadLocations() {
  axios.get("http://localhost:8080/api/v1/targetLocation/downloadSearchData")
      .then((response) => {
        const  content = new Blob([JSON.stringify(response.data)],{ type: 'text/plain;charset=utf-8' })
        const fileName = `test.txt`
        saveAs(content, fileName)
      }, (error) => {
        console.log(error);
      });
}

Java | Springboot 服务 -

public ByteArrayOutputStream downloadSearchData() throws IOException {
    BasicAWSCredentials awsCredentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
    AmazonS3 s3client = AmazonS3ClientBuilder
            .standard()
            .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
            .withRegion(awsRegion)
            .build();

    S3Object s3Object = s3client.getObject("downloadable-cases", "7863784198_2021-08-16T13_30_06.690Z.json");
    InputStream is = s3Object.getObjectContent();
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    int len;
    byte[] buffer = new byte[4096];
    while ((len = is.read(buffer, 0, buffer.length)) != -1) {
        outputStream.write(buffer, 0, len);
    }
    return outputStream;
}

这有效,接受它下载到项目,而不是我的机器(这是重点)-

public void downloadSearchData() throws IOException {
    BasicAWSCredentials awsCredentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
    AmazonS3 s3client = AmazonS3ClientBuilder
            .standard()
            .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
            .withRegion(awsRegion)
            .build();

    S3Object s3object = s3client.getObject(
            "downloadable-cases", "7863784198_2021-08-16T13_30_06.690Z.json"
    );
    S3ObjectInputStream inputStream = s3object.getObjectContent();
    FileUtils.copyInputStreamToFile(inputStream, new File("hello.txt"));
}

这里有几点评论:

1 - 您使用的是旧版 V1 Amazon S3 Java API。您应该考虑迁移到 V2,因为亚马逊建议使用 V1。

适用于 Java 2.x 的 AWS 开发工具包是对版本 1.x 代码库的重大重写。它建立在 Java 8+ 之上,并添加了几个经常请求的功能。其中包括对非阻塞 I/O 的支持以及在 运行 时插入不同 HTTP 实现的能力。

Amazon SDK for Java V2 Developer Guide

2 - 使用 Amazon Java V2 APIs 时,您无需在代码中硬编码您的信誉。要使用 V2 和 creds,请参阅:Using credentials.

由于您正在使用 Spring BOOT 应用程序,这里是一个使用 Amazon S3 Java V2 API 和 Spring BOOT 的示例。此应用程序可让您将位于 S3 存储桶中的对象下载到您的浏览器。

下载的对象有效,我可以打开并查看它(它不是空的或损坏的):

Amazon S3 Java 从存储桶中获取对象的 V2 代码是:

// Get the byte[] from this AWS S3 object.
public byte[] getObjectBytes (String bucketName, String keyName) {

    s3 = getClient();

    try {
        GetObjectRequest objectRequest = GetObjectRequest
                .builder()
                .key(keyName)
                .bucket(bucketName)
                .build();
        
        ResponseBytes<GetObjectResponse> objectBytes = s3.getObjectAsBytes(objectRequest);
        byte[] data = objectBytes.asByteArray();
        return data;

    } catch (S3Exception e) {
        System.err.println(e.awsErrorDetails().errorMessage());
        System.exit(1);
    }
    return null;
}

请参阅这篇开发人员文章,了解如何在 Spring 启动应用程序中使用 Amazon S3 Java V2 API 和其他服务:

Creating an example AWS photo analyzer application using the AWS SDK for Java

此 link 将指导您创建此 Spring 应用程序....

您似乎已经关注了 the official AWS example "Download an Object",因此您的代码看起来是正确的。您忘记在最后调用 is.close() 来关闭输入流,但是这不太可能是问题所在。

您可以使用 try-with-resource 块和 InputStream.transferTo() 方法来简化您的代码:

var s3Object = s3client.getObject("downloadable-cases", "7863784198_2021-08-16T13_30_06.690Z.json");
var out = new ByteArrayOutputStream();
try (var in = s3Object.getObjectContent()) {
  in.transferTo(out);
}
return out;

可能S3文件没有内容,如果你使用AWS控制台下载它会显示任何内容吗?如果它在 AWS 控制台上运行,您应该使用调试器来查看您的代码中发生了什么。