Question:
Can anyone tell me what is wrong with the following code such that a large file upload (>10GB) always fails with ResetException: Failed to reset the request input stream
?
The failure always happens after a while (i.e. after around 15 minutes), which must mean that the upload process is executing only to fail somewhere in the middle.
Here’s what I’ve tried to debug the problem:
in.marksSupported() == false // checking if mark is supported on my FileInputStream
I highly suspect that this is the problem, since the S3 SDK seems to want to do a reset operation at some point during the upload, probably if the connection is lost or if the transfer process encounters some error.
- Wrapping my
FileInputStream
within aBufferedInputStream
to enable marking. Now callingin.marksSupported()
returnstrue
, meaning that mark support is there. Strangely, the upload process still fails with the same kind of error. - Adding
putRequest.getRequestClientOptions.setReadLimit(n)
, wheren=100000 (100kb), and 800000000 (800mb)
but it still throws the same error. I suspect because this parameter is used to reset the stream, which, as stated above, isn’t supported on aFileInputStream
Interestingly, the same problem doesn’t happen on my AWS development account. I assume that is just because the dev account is not under a heavy load as my production account, meaning that the upload process can execute as smoothly as possible without any failure at all.
Please have a look at my code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
object S3TransferExample { // in main class def main(args: Array[String]): Unit = { ... val file = new File("/mnt/10gbfile.zip") val in = new FileInputStream(file) // val in = new BufferedInputStream(new FileInputStream(file)) --> tried wrapping file inputstream in a buffered input stream, but it didn't help.. upload("mybucket", "mykey", in, file.length, "application/zip").waitForUploadResult ... } val awsCred = new BasicAWSCredentials("access_key", "secret_key") val s3Client = new AmazonS3Client(awsCred) val tx = new TransferManager(s3Client) def upload(bucketName: String, keyName: String, inputStream: InputStream, contentLength: Long, contentType: String, serverSideEncryption: Boolean = true, storageClass: StorageClass = StorageClass.ReducedRedundancy ):Upload = { val metaData = new ObjectMetadata metaData.setContentType(contentType) metaData.setContentLength(contentLength) if(serverSideEncryption) { metaData.setSSEAlgorithm(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION) } val putRequest = new PutObjectRequest(bucketName, keyName, inputStream, metaData) putRequest.setStorageClass(storageClass) putRequest.getRequestClientOptions.setReadLimit(100000) tx.upload(putRequest) } } |
Here is the complete stack trace:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
Unable to execute HTTP request: mybucket.s3.amazonaws.com failed to respond org.apache.http.NoHttpResponseException: mybuckets3.amazonaws.com failed to respond at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:143) ~[httpclient-4.3.4.jar:4.3.4] at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57) ~[httpclient-4.3.4.jar:4.3.4] at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:260) ~[httpcore-4.3.2.jar:4.3.2] at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:283) ~[httpcore-4.3.2.jar:4.3.2] at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:251) ~[httpclient-4.3.4.jar:4.3.4] at org.apache.http.impl.conn.ManagedClientConnectionImpl.receiveResponseHeader(ManagedClientConnectionImpl.java:197) ~[httpclient-4.3.4.jar:4.3.4] at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:271) ~[httpcore-4.3.2.jar:4.3.2] at com.amazonaws.http.protocol.SdkHttpRequestExecutor.doReceiveResponse(SdkHttpRequestExecutor.java:66) ~[aws-java-sdk-core-1.9.13.jar:na] at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123) ~[httpcore-4.3.2.jar:4.3.2] at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:685) ~[httpclient-4.3.4.jar:4.3.4] at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:487) ~[httpclient-4.3.4.jar:4.3.4] at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863) ~[httpclient-4.3.4.jar:4.3.4] at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) ~[httpclient-4.3.4.jar:4.3.4] at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57) ~[httpclient-4.3.4.jar:4.3.4] at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:685) [aws-java-sdk-core-1.9.13.jar:na] at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:460) [aws-java-sdk-core-1.9.13.jar:na] at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:295) [aws-java-sdk-core-1.9.13.jar:na] at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3710) [aws-java-sdk-s3-1.9.13.jar:na] at com.amazonaws.services.s3.AmazonS3Client.doUploadPart(AmazonS3Client.java:2799) [aws-java-sdk-s3-1.9.13.jar:na] at com.amazonaws.services.s3.AmazonS3Client.uploadPart(AmazonS3Client.java:2784) [aws-java-sdk-s3-1.9.13.jar:na] at com.amazonaws.services.s3.transfer.internal.UploadCallable.uploadPartsInSeries(UploadCallable.java:259) [aws-java-sdk-s3-1.9.13.jar:na] at com.amazonaws.services.s3.transfer.internal.UploadCallable.uploadInParts(UploadCallable.java:193) [aws-java-sdk-s3-1.9.13.jar:na] at com.amazonaws.services.s3.transfer.internal.UploadCallable.call(UploadCallable.java:125) [aws-java-sdk-s3-1.9.13.jar:na] at com.amazonaws.services.s3.transfer.internal.UploadMonitor.call(UploadMonitor.java:129) [aws-java-sdk-s3-1.9.13.jar:na] at com.amazonaws.services.s3.transfer.internal.UploadMonitor.call(UploadMonitor.java:50) [aws-java-sdk-s3-1.9.13.jar:na] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_40] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_40] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_40] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_40] 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.executeOneRequest(AmazonHttpClient.java:636) at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:460) at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:295) at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3710) at com.amazonaws.services.s3.AmazonS3Client.doUploadPart(AmazonS3Client.java:2799) at com.amazonaws.services.s3.AmazonS3Client.uploadPart(AmazonS3Client.java:2784) at com.amazonaws.services.s3.transfer.internal.UploadCallable.uploadPartsInSeries(UploadCallable.java:259) at com.amazonaws.services.s3.transfer.internal.UploadCallable.uploadInParts(UploadCallable.java:193) at com.amazonaws.services.s3.transfer.internal.UploadCallable.call(UploadCallable.java:125) at com.amazonaws.services.s3.transfer.internal.UploadMonitor.call(UploadMonitor.java:129) at com.amazonaws.services.s3.transfer.internal.UploadMonitor.call(UploadMonitor.java:50) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) Caused by: java.io.IOException: Resetting to invalid mark at java.io.BufferedInputStream.reset(BufferedInputStream.java:448) at com.amazonaws.internal.SdkBufferedInputStream.reset(SdkBufferedInputStream.java:106) at com.amazonaws.internal.SdkFilterInputStream.reset(SdkFilterInputStream.java:103) at com.amazonaws.event.ProgressInputStream.reset(ProgressInputStream.java:139) at com.amazonaws.internal.SdkFilterInputStream.reset(SdkFilterInputStream.java:103) at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:634) |
Answer:
This definitely looks like a bug, which I have reported. The solution is to use the other constructor which accepts a File
instead of InputStream
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
def upload(bucketName: String, keyName: String, file: File, contentLength: Long, contentType: String, serverSideEncryption: Boolean = true, storageClass: StorageClass = StorageClass.ReducedRedundancy ):Upload = { val metaData = new ObjectMetadata metaData.setContentType(contentType) metaData.setContentLength(contentLength) if(serverSideEncryption) { metaData.setSSEAlgorithm(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION) } val putRequest = new PutObjectRequest(bucketName, keyName, file) putRequest.setStorageClass(storageClass) putRequest.getRequestClientOptions.setReadLimit(100000) putRequest.setMetadata(metaData) tx.upload(putRequest) } } |