【问题标题】:Is it possible to write to s3 via a stream using s3 java sdk是否可以使用 s3 java sdk 通过流写入 s3
【发布时间】:2018-07-09 12:23:29
【问题描述】:

通常当文件必须上传到 s3 时,必须先将其写入磁盘,然后才能使用 TransferManager api 之类的东西上传到云端。如果上传没有按时完成,这会导致数据丢失(应用程序出现故障并在不同的服务器上重新启动等)。所以我想知道是否可以直接通过网络将所需的云位置作为接收器写入流。

【问题讨论】:

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


    【解决方案1】:

    你没有说你使用的是什么语言,但我会根据你的大小写假设 Java。在这种情况下,答案是肯定的:TransferManager 有一个采用 PutObjectRequestupload() 方法,您可以围绕流构造该对象。

    但是,有两个重要的警告。第一个在PutObjectRequest 的文档中:

    直接从输入流上传时,必须先指定内容长度,然后才能将数据上传到 Amazon S3

    因此,在开始之前,您必须知道要上传多少数据。如果您正在接收来自网络的上传并且有 Content-Length 标头,那么您可以从中获取大小。如果您只是读取任意长度的数据流,则必须先将其写入文件(或者 SDK 会)。

    第二个警告是,这并不能防止数据丢失:您的程序仍然可能在读取数据的过程中崩溃。它阻止的一件事是在将数据存储到 S3 之前向用户返回成功代码,但无论如何您都可以使用文件来执行此操作。

    【讨论】:

      【解决方案2】:

      有可能:

      AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
          .build();
      s3Client.putObject("bucket", "key", youtINputStream, s3MetData)
      

      AmazonS3.putObject

      【讨论】:

        【解决方案3】:

        令人惊讶的是,这在标准 Java SDK 中是不可能的(在撰写本文时)。无论如何感谢3rd party library,您至少可以避免将大量数据缓冲到内存或磁盘,因为它在内部缓冲约 5MB 部分并自动上传它们within multipart 为您上传。

        SDK 库中还有github issue open,可以关注更新。

        【讨论】:

          【解决方案4】:
          public void saveS3Object(String key, InputStream inputStream) throws Exception {
                  List<PartETag> partETags = new ArrayList<>();
                  InitiateMultipartUploadRequest initRequest = new
                          InitiateMultipartUploadRequest(bucketName, key);
          
                  InitiateMultipartUploadResult initResponse =
                          s3.initiateMultipartUpload(initRequest);
          
                  int partSize = 5242880; // Set part size to 5 MB.
          
                  try {
                      byte b[] = new byte[partSize];
                      int len = 0;
                      int i = 1;
                      
                      while ((len = inputStream.read(b)) >= 0) {
                          // Last part can be less than 5 MB. Adjust part size.
          
                          ByteArrayInputStream partInputStream = new ByteArrayInputStream(b,0,len);
          
                          UploadPartRequest uploadRequest = new UploadPartRequest()
                                  .withBucketName(bucketName).withKey(key)
                                  .withUploadId(initResponse.getUploadId()).withPartNumber(i)
                                  .withFileOffset(0)
                                  .withInputStream(partInputStream)
                                  .withPartSize(len);
          
                          partETags.add(
                                  s3.uploadPart(uploadRequest).getPartETag());
                          
                          i++;
                      }
          
                      
                      CompleteMultipartUploadRequest compRequest = new
                              CompleteMultipartUploadRequest(
                              bucketName,
                              key,
                              initResponse.getUploadId(),
                              partETags);
          
                      s3.completeMultipartUpload(compRequest);
                  } catch (Exception e) {
                      s3.abortMultipartUpload(new AbortMultipartUploadRequest(
                              bucketName, key, initResponse.getUploadId()));
                  }
          }
          

          【讨论】:

          • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助,质量更高,更有可能吸引投票。
          • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
          猜你喜欢
          • 2010-10-06
          • 2021-12-28
          • 2018-08-26
          • 1970-01-01
          • 2016-08-14
          • 2016-07-24
          • 2015-07-05
          • 2011-01-08
          • 1970-01-01
          相关资源
          最近更新 更多