Search code examples
amazon-s3aws-sdkaws-java-sdk

Why we need to setReadLimit(int) in AWS S3 Java client


I am working on AWS Java S3 Library.

This is my code which is uploading the file to s3 using High-Level API of AWS.

        ClientConfiguration configuration = new ClientConfiguration();
        configuration.setUseGzip(true);
        configuration.setConnectionTTL(1000 * 60 * 60);
        AmazonS3Client amazonS3Client = new AmazonS3Client(configuration);
        TransferManager transferManager = new TransferManager(amazonS3Client);

        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(message.getBodyLength());
        objectMetadata.setContentType("image/jpg");

        transferManager.getConfiguration().setMultipartUploadThreshold(1024 * 10);

        PutObjectRequest request = new PutObjectRequest("test", "/image/test", inputStream, objectMetadata);
        request.getRequestClientOptions().setReadLimit(1024 * 10);
        request.setSdkClientExecutionTimeout(1000 * 60 * 60);

        Upload upload = transferManager.upload(request);
        upload.waitForCompletion();

I am trying to upload a large file. It is working properly but sometimes I am getting below error. I have set readLimit as (1024*10).

2019-04-05 06:41:05,679 ERROR [com.demo.AwsS3TransferThread] (Aws-S3-upload) Error in saving File[media/image/osc/54/54ec3f2f-a938-473c-94b7-a55f39aac4a6.png] on S3[demo-test]: com.amazonaws.ResetException: Failed to reset the request input stream;  If the request involves an input stream, the maximum stream buffer size can be configured via request.getRequestClientOptions().setReadLimit(int)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.resetRequestInputStream(AmazonHttpClient.java:1221)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1042)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:948)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:661)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:635)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:618)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$300(AmazonHttpClient.java:586)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:573)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:445)
    at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4041)
    at com.amazonaws.services.s3.AmazonS3Client.doUploadPart(AmazonS3Client.java:3041)
    at com.amazonaws.services.s3.AmazonS3Client.uploadPart(AmazonS3Client.java:3026)
    at com.amazonaws.services.s3.transfer.internal.UploadCallable.uploadPartsInSeries(UploadCallable.java:255)
    at com.amazonaws.services.s3.transfer.internal.UploadCallable.uploadInParts(UploadCallable.java:189)
    at com.amazonaws.services.s3.transfer.internal.UploadCallable.call(UploadCallable.java:121)
    at com.amazonaws.services.s3.transfer.internal.UploadMonitor.call(UploadMonitor.java:139)
    at com.amazonaws.services.s3.transfer.internal.UploadMonitor.call(UploadMonitor.java:47)

What is the perpose of readLimit? How it will usefull? What should I do to avoid this kind of exception?


Solution

  • After researching on this for 1 week, I have found that if your uploading file size is less than 48GB then you can set readLimit value 5.01MB.

    because AWS dividing file into multiple parts and each part size is value is 5MB(If you have not changed minimum part size value). as per the AWS specs, last part size is less than 5MB. so I have set readLimit 5MB and it solves the issue.

    InputStream readLimit purpose:

    Marks the current position in this input stream. A subsequent call to the reset method repositions this stream at the last marked position so that subsequent reads re-read the same bytes.Readlimit arguments tells this input stream to allow that many bytes to be read before the mark position gets invalidated. The general contract of mark is that, if the method markSupported returns, the stream somehow remembers all the bytes read after the call to mark and stands ready to supply those same bytes again if and whenever the method reset is called. However, the stream is not required to remember any data at all if more than readLimit bytes are read from the stream before reset is called.