【问题标题】:How can I read an AWS S3 File with Java?如何使用 Java 读取 AWS S3 文件?
【发布时间】:2015-04-18 13:40:46
【问题描述】:

我尝试将文件从 AWS S3 读取到我的 java 代码:

  File file = new File("s3n://mybucket/myfile.txt");
  FileInputStream fileInput = new FileInputStream(file);

然后我得到一个错误:

java.io.FileNotFoundException: s3n:/mybucket/myfile.txt (No such file or directory)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:146)

有没有办法从 AWS S3 打开/读取文件?非常感谢!

【问题讨论】:

    标签: java amazon-web-services amazon-s3


    【解决方案1】:

    在 2019 年,从 S3 读取文件的方式更加优化:

    private final AmazonS3 amazonS3Client = AmazonS3ClientBuilder.standard().build();
    
    private Collection<String> loadFileFromS3() {
        try (final S3Object s3Object = amazonS3Client.getObject(BUCKET_NAME,
                                                                FILE_NAME);
            final InputStreamReader streamReader = new InputStreamReader(s3Object.getObjectContent(), StandardCharsets.UTF_8);
            final BufferedReader reader = new BufferedReader(streamReader)) {
            return reader.lines().collect(Collectors.toSet());
        } catch (final IOException e) {
            log.error(e.getMessage(), e)
            return Collections.emptySet();
        }
    }
    

    【讨论】:

    • 以何种方式优化(澄清一下)?这最终会将所有内容都拉入内存而不使用流语义(如果您有小文件则很好,如果您有 100GB 文件则不好)。
    【解决方案2】:

    我们也可以使用software.amazon.awssdk:s3

     //Assuming the credentials are read from Environment Variables, so no hardcoding here
    
        S3Client client = S3Client.builder()
                            .region(regionSelected)
                            .build();
        
        GetObjectRequest getObjectRequest = GetObjectRequest.builder()
                        .bucket(bucketName)
                        .key(fileName)
                        .build();
        
        ResponseInputStream<GetObjectResponse> responseInputStream = client.getObject(getObjectRequest);
    
        InputStream stream = new ByteArrayInputStream(responseInputStream.readAllBytes());
        
        
        System.out.println("Content :"+ new String(responseInputStream.readAllBytes(), StandardCharsets.UTF_8));
    

    【讨论】:

    • 注意 InputStream.readAllBytes() 可从 Java 9 获得
    • @hertzsprung 感谢您指出这一点!是的,我记得我使用的是 Java 11
    【解决方案3】:

    这是我的解决方案。我正在使用 Spring Boot 2.4.3

    创建 amazon s3 客户端

    AmazonS3 amazonS3Client = AmazonS3ClientBuilder
                    .standard()
                    .withRegion("your-region")
                    .withCredentials(
                            new AWSStaticCredentialsProvider(
                                new BasicAWSCredentials("your-access-key", "your-secret-access-key")))
                    .build();
    

    创建一个亚马逊转账客户端。

    TransferManager transferManagerClient = TransferManagerBuilder.standard()
                    .withS3Client(amazonS3Client)
                    .build();
    

    在/tmp/{your-s3-key}中创建一个临时文件,这样我们就可以将我们下载的文件放在这个文件中。

    File file = new File(System.getProperty("java.io.tmpdir"), "your-s3-key"); 
    
    try {
        file.createNewFile(); // Create temporary file
    } catch (IOException e) {
        e.printStackTrace();
    }
    
    file.mkdirs();  // Create the directory of the temporary file
    

    然后,我们使用 transfer manager client

    从 s3 下载文件
    // Note that in this line the s3 file downloaded has been transferred in to the temporary file that we created
    Download download = transferManagerClient.download(
                   new GetObjectRequest("your-s3-bucket-name", "your-s3-key"), file); 
    
    // This line blocks the thread until the download is finished
    download.waitForCompletion();  
    
    

    现在 s3 文件已成功传输到我们创建的 临时文件 中。我们可以得到临时文件的InputStream。

    InputStream input = new DataInputStream(new FileInputStream(file));
    

    因为临时文件已经不需要了,我们直接删除了。

    file.delete();
    

    【讨论】:

    • 嗨,蓝天,你能解释一下这段代码在做什么吗?
    • @bsheps 我刚刚编辑了我的答案,怎么样?
    【解决方案4】:

    java中读取S3文件的步骤可以是:

    1. 创建 AmazonS3Client。
    2. 使用存储桶名称和密钥创建 S3Object。
    3. 使用 S3Object 创建缓冲区读取器并逐行读取文件。

    1 >>>

        BasicAWSCredentials awsCreds = new BasicAWSCredentials("accessKey", "secretKey");
        AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
                .withRegion("region_name_here").build();  
    

    2 >>>

       S3Object object = s3Client.getObject(new GetObjectRequest("bucketName", "key"));
    

    3 >>>

       BufferedReader reader = new BufferedReader(new InputStreamReader(object.getObjectContent()));
    
        String s = null;
        while ((s = reader.readLine()) != null)
        {
            System.out.println(s);
            //your business logic here
        }
    

    谢谢。

    【讨论】:

      【解决方案5】:

      如果文件的内容是一个字符串,那么你可以使用getObjectAsString。否则,您可以在getObjectContent() 上使用IOUtils.toByteArray 将文件内容读入字节数组。

      显然,这些最适合用于易于装入内存的小型 S3 对象。

      private final AmazonS3 amazonS3Client = AmazonS3ClientBuilder.standard().build();
      
      private String loadStringFromS3() {
          try {
              return amazonS3Client.getObjectAsString(BUCKET_NAME, FILE_NAME);
          } catch (final IOException e) {
              log.error(e.getMessage(), e)
              return null;
          }
      }
      
      private byte[] loadDataFromS3() {
          try (final S3Object s3Object = amazonS3Client.getObject(BUCKET_NAME, FILE_NAME)) {
              return IOUtils.toByteArray(s3Object.getObjectContent());
          } catch (final IOException e) {
              log.error(e.getMessage(), e)
              return null;
          } finally {
              IOUtils.closeQuietly(object, log);
          }
      }
      

      【讨论】:

        【解决方案6】:

        Java 中的“文件”类不理解 S3 的存在。 Here's an example of reading a file from the AWS documentation:

        AmazonS3 s3Client = new AmazonS3Client(new ProfileCredentialsProvider());        
        S3Object object = s3Client.getObject(new GetObjectRequest(bucketName, key));
        InputStream objectData = object.getObjectContent();
        // Process the objectData stream.
        objectData.close();
        

        【讨论】:

        • 谢谢!我可以使用 maven 中的相应 jar(对于那些类)吗?
        • @tedder42,如果对象内容是电子邮件,是否有任何 API 来处理数据。我想获取电子邮件内容,发件人,发件人等
        • @edwiser 提出一个新问题并将其链接到此处 - 需要更多信息。
        • 似乎已弃用,使用AmazonS3 s3Client = AmazonS3ClientBuilder.standard().build()
        猜你喜欢
        • 2017-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-23
        • 1970-01-01
        • 2016-07-27
        • 2019-08-21
        • 2015-08-30
        相关资源
        最近更新 更多