【问题标题】:Unable to reset stream after calculating AWS4 signature计算 AWS4 签名后无法重置流
【发布时间】:2018-03-03 18:34:05
【问题描述】:

有一段代码。

 List<PartETag> uploadPartsOfAsset(AssetUploadRequestVO requestVO) {
    final SingleClient singleClient = clientProvider.getClient(requestVO.getAssetKind());
    final List<PartETag> parts = new ArrayList<>();
    final String key = String.join(DELIMITER, requestVO.getClientName(), requestVO.getAssetGroup(), requestVO.getAssetName());

    final long contentSize = requestVO.getContentSize();
    long position = 0;
    long partSize = minPartSize;

    final UploadPartRequest request = new UploadPartRequest();

    try (InputStream source = requestVO.getSource()) {
        for (int partNumber = requestVO.getPartNumber(); position < requestVO.getContentSize(); partNumber++) {
            partSize = Math.min(partSize, (requestVO.getContentSize() - position));

            final long nextFilePosition = position + partSize;
            if((requestVO.getContentSize() - nextFilePosition) < minPartSize){
                partSize = contentSize - position;
                position = contentSize;
            }

            request.withBucketName(singleClient.getBucketName())
                    .withKey(key)
                    .withUploadId(requestVO.getUploadId()).withPartNumber(partNumber)
                    .withInputStream(source)
                    .withPartSize(partSize);

            PartETag partETag = null;
            try {
                partETag = singleClient.getAmazonS3Client().uploadPart(request).getPartETag();
            } catch (AmazonS3Exception e){
                throw new AssetNotFoundException(e.getMessage());
            }
            parts.add(partETag);

            position += partSize;
        }
    } catch (IOException e) {
        throw new AssetUploadException("The asset cannot be upload.", e);
    }

    return parts;
}

AssetUploadRequestVO.getSource() 是 S3ObjectInputStream 的实例。问题是这个抛出异常:

com.amazonaws.SdkClientException: Unable to reset stream after calculating AWS4 signature
at com.amazonaws.auth.AWS4Signer.calculateContentHash(AWS4Signer.java:542) ~[aws-java-sdk-core-1.11.125.jar:na]
at com.amazonaws.services.s3.internal.AWSS3V4Signer.calculateContentHash(AWSS3V4Signer.java:118) ~[aws-java-sdk-s3-1.11.125.jar:na]
at com.amazonaws.auth.AWS4Signer.sign(AWS4Signer.java:213) ~[aws-java-sdk-core-1.11.125.jar:na]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1164) ~[aws-java-sdk-core-1.11.125.jar:na]

...

Caused by: java.io.IOException: Resetting to invalid mark
at java.io.BufferedInputStream.reset(BufferedInputStream.java:448) ~[na:1.8.0_144]
at com.amazonaws.internal.SdkBufferedInputStream.reset(SdkBufferedInputStream.java:106) ~[aws-java-sdk-core-1.11.125.jar:na]
at com.amazonaws.internal.SdkFilterInputStream.reset(SdkFilterInputStream.java:102) ~[aws-java-sdk-core-1.11.125.jar:na]
at com.amazonaws.event.ProgressInputStream.reset(ProgressInputStream.java:168) ~[aws-java-sdk-core-1.11.125.jar:na]

我已经找到了解决这个错误的方法,但问题是我真的不明白为什么会发生。

所以解决方案是将 S3ObjectInputStream 更改为其他输入流。就我而言,我已将其更改为:

new ByteArrayInputStream(IOUtils.toByteArray(requestVO.getSource()))

那么有人可以帮我解释一下问题所在,我的解决方案好吗? 另外我想补充一点,如果我们使用 S3 并且仅使用 ECS 失败,则此代码可以正常工作。

【问题讨论】:

    标签: java amazon-ec2 inputstream java-io


    【解决方案1】:

    问题是从 EC2 返回的 Stream 不支持标记。您必须将其保存到 FileInputStream 或 ByteArrayInputStream。或者在我的情况下合并亚马逊内部的所有内容而不将其提取到我的服务器

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-20
      • 1970-01-01
      • 2019-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-24
      • 2015-05-08
      相关资源
      最近更新 更多