Closed gunsh closed 11 months ago
@gunsh Good afternoon. The ticket description is pretty confusing but somewhat understandable. Could you please share the exact part size and file size you are using to reproduce the issue? Also, do we really need to make large file fo size (10,000 x 5251072 bytes)? This would make is easier for us to validate your findings.
In the meanwhile, trying to reproduce the issue using below steps:
fsutil file createnew test.txt 52439040000
to create a file of size 10000 * ((5*1024*1024) + 1024))
(1024 bytes greater than 5MB * 10000)Use below code to upload file for non-seekable stream scenario:
using (AmazonS3Client amazonS3Client = new AmazonS3Client(RegionEndpoint.USEast2))
{
TransferUtility transferUtility = new TransferUtility(amazonS3Client);
Stream nonSeekableWebStream= GenerateUnseekableStreamFromFile(@"C:\PerfLogs\test.txt");
TransferUtilityUploadRequest transferUtilityUploadRequest = new TransferUtilityUploadRequest()
{
BucketName = bucketName,
Key = "test-nonSeekable.txt",
InputStream = nonSeekableWebStream,
PartSize = 52793626
};
await transferUtility.UploadAsync(transferUtilityUploadRequest);
}
UnseekableStream GenerateUnseekableStreamFromFile(string filePath) { try { UnseekableStream unseekableStream = new UnseekableStream(filePath, FileMode.Open); unseekableStream.Position = 0; return unseekableStream; } catch (Exception ex) { Console.WriteLine($"An error occurred while generating the stream: {ex.Message}"); throw; } }
public class UnseekableStream : FileStream { public UnseekableStream(string path, FileMode mode) : base(path, mode) { }
public override bool CanSeek
{
get => false;
}
public override long Length
{
get => throw new NotSupportedException();
}
}
Thanks,
Ashish
Hello and thanks for a quick response.
After running your code I can see the exact same log output. I have not let it run until completion but I am guessing the outcome would be the same. Would you agree that your own sample reproduces the issue described? I do have a reservation with respect to your math 10000 * ((5*1024*1024) + 1024))
. I believe you need to make the file at least as large as 10,000 * 5,251,072 +1 bytes = 52,510,720,001
for the issue to rear its ugly head.
I do have a proprietary stream implementation (not able to share) but your quick and dirty unseekable stream based on FileStream
is really great.
Anyhow, the point I am trying to make is that the suggested part size 52793626
is ignored. Part size of 5251072
is being used instead.
Hello and thanks for a quick response.
After running your code I can see the exact same log output. I have not let it run until completion but I am guessing the outcome would be the same. Would you agree that your own sample reproduces the issue described? I do have a reservation with respect to your math
10000 * ((5*1024*1024) + 1024))
. I believe you need to make the file at least as large as10,000 * 5,251,072 +1 bytes = 52,510,720,001
for the issue to rear its ugly head.I do have a proprietary stream implementation (not able to share) but your quick and dirty unseekable stream based on
FileStream
is really great.Anyhow, the point I am trying to make is that the suggested part size
52793626
is ignored. Part size of5251072
is being used instead.
@gunsh Somehow, with the above values I'm unable to reproduce the issue. Could you please share the definitive values which could reproduce the issue? I'm unsure if there are any design considerations for ignoring part size for non-seekable streams.
CC @peterrsongg
I can easily reproduce this. Please use your sample code but make sure to create a file of this size 52510720001 (or greater). If you take a closer look at my original post, you will see that the logged part size is: 5251072. If you now do the math: 10,000 * 5,251,072 = 52,510,720,000. This is largest file size that will work. If you add just one more byte to it, the process will fail with "Part number must be an integer between 1 and 10000, inclusive".
Looking at the source code reveals that PartSize
is ignored and a different smaller value (as previously described) is used to create a MemoryStream
. I don't think this is easy to fix since creating a huge MemoryStream
for holding each and every part is going to be very inefficient and in some cases impossible due to RAM considerations. I am guessing that MemoryStream
is now being used so that an unseekable stream is made seekable. The stream is used twice. Once for calculating a hash, second time for actually sending the part. Anyway, I will let you figure it out. I would just like a confirmation that the issue is now reproducible.
If anyone stumbles upon this before the issue is fixed, there is a somewhat ugly workaround. Instead of using a part upload, one can use PutObject
to upload individual parts up to 5GB and then immediately do a CopyPart
from an existing temporary S3 object, followed by a removal of the temporary object. Parts are therefore not directly uploaded but copied from existing temporary objects. This works well if you have all the required permissions on the bucket.
Can you please confirm you can at least reproduce the issue now?
@gunsh I'm sorry that we haven't gotten to this yet. With Reinvent this week, it's been hard to find time to prioritize this. This will most likely be looked at next week, when ReInvent is over. Appreciate your patience.
Can you please confirm you can at least reproduce the issue now?
@gunsh Good afternoon. I was able to reproduce the issue with file of size 52510720001
and using the code in https://github.com/aws/aws-sdk-net/issues/3108#issuecomment-1821833134. It gave the error Amazon.S3.AmazonS3Exception: 'Part number must be an integer between 1 and 10000, inclusive'
.
Amazon Verbose: 10002 : Single encoded /test-nonSeekable.txt with endpoint https://sometestbucket.s3.us-east-2.amazonaws.com/ for canonicalization: /test-nonSeekable.txt
Amazon Verbose: 10000 : Received response (truncated to 1024 bytes): []
Amazon Verbose: 10001 : Uploaded part 10000. (Last part = False, Part size = 5251072, Upload Id: l3gf72ezP3rlusqgdf4zSrEo9832nD_WMV08duC5bPgrucSzVYFeVfLa9FMHUq6yY1f59c_P6sCfaBYPemJrhRcVWLxeyBapXv5IrIPGcYQ4INk_RW3AwbulEHKFXB6ptrLVJakfQj5AYscqB58J9A--)
Amazon Verbose: 10003 : Single encoded /test-nonSeekable.txt with endpoint https://sometestbucket.s3.us-east-2.amazonaws.com/ for canonicalization: /test-nonSeekable.txt
Amazon Error: 10001 : An exception of type HttpErrorResponseException was handled in ErrorHandler., Amazon.Runtime.Internal.HttpErrorResponseException: Exception of type 'Amazon.Runtime.Internal.HttpErrorResponseException' was thrown.
at Amazon.Runtime.HttpWebRequestMessage.ProcessHttpResponseMessage(HttpResponseMessage responseMessage) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\HttpHandler\_netstandard\HttpRequestMessageFactory.cs:line 594
at Amazon.Runtime.HttpWebRequestMessage.GetResponseAsync(CancellationToken cancellationToken) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\HttpHandler\_netstandard\HttpRequestMessageFactory.cs:line 545
at Amazon.Runtime.Internal.HttpHandler`1.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\HttpHandler\HttpHandler.cs:line 185
at Amazon.Runtime.Internal.RedirectHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\RedirectHandler.cs:line 59
at Amazon.Runtime.Internal.Unmarshaller.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\Unmarshaller.cs:line 85
at Amazon.S3.Internal.AmazonS3ResponseHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Services\S3\Custom\Internal\AmazonS3ResponseHandler.cs:line 58
at Amazon.Runtime.Internal.ErrorHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\ErrorHandler.cs:line 99
Amazon Error: 10002 : Received error response: [<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>InvalidArgument</Code><Message>Part number must be an integer between 1 and 10000, inclusive</Message><ArgumentName>partNumber</ArgumentName><ArgumentValue>10001</ArgumentValue><RequestId>6R09P7PXPY8HTD0R</RequestId><HostId>47WV3jn0QkmieR7jYqI/82Um9cdFWuT0v3T6KvQbkoeZsOZxWwGKHi6i4QjBwnGPwT0FSKA3VA8=</HostId></Error>], Amazon.S3.AmazonS3Exception: Part number must be an integer between 1 and 10000, inclusive
---> Amazon.Runtime.Internal.HttpErrorResponseException: Exception of type 'Amazon.Runtime.Internal.HttpErrorResponseException' was thrown.
at Amazon.Runtime.HttpWebRequestMessage.ProcessHttpResponseMessage(HttpResponseMessage responseMessage) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\HttpHandler\_netstandard\HttpRequestMessageFactory.cs:line 594
at Amazon.Runtime.HttpWebRequestMessage.GetResponseAsync(CancellationToken cancellationToken) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\HttpHandler\_netstandard\HttpRequestMessageFactory.cs:line 545
at Amazon.Runtime.Internal.HttpHandler`1.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\HttpHandler\HttpHandler.cs:line 185
at Amazon.Runtime.Internal.RedirectHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\RedirectHandler.cs:line 59
at Amazon.Runtime.Internal.Unmarshaller.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\Unmarshaller.cs:line 85
at Amazon.S3.Internal.AmazonS3ResponseHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Services\S3\Custom\Internal\AmazonS3ResponseHandler.cs:line 58
at Amazon.Runtime.Internal.ErrorHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\ErrorHandler.cs:line 99
--- End of inner exception stack trace ---
Amazon Information: 1 : Resolved DefaultConfigurationMode for RegionEndpoint [us-east-1] to [Legacy].
Amazon Information: 2 : Resolved DefaultConfigurationMode for RegionEndpoint [us-east-1] to [Legacy].
Amazon Error: 10003 : AmazonS3Exception making request UploadPartRequest to https://testbucket-issue1880.s3.us-east-2.amazonaws.com/. Attempt 1., Amazon.S3.AmazonS3Exception: Part number must be an integer between 1 and 10000, inclusive
---> Amazon.Runtime.Internal.HttpErrorResponseException: Exception of type 'Amazon.Runtime.Internal.HttpErrorResponseException' was thrown.
at Amazon.Runtime.HttpWebRequestMessage.ProcessHttpResponseMessage(HttpResponseMessage responseMessage) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\HttpHandler\_netstandard\HttpRequestMessageFactory.cs:line 594
at Amazon.Runtime.HttpWebRequestMessage.GetResponseAsync(CancellationToken cancellationToken) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\HttpHandler\_netstandard\HttpRequestMessageFactory.cs:line 545
at Amazon.Runtime.Internal.HttpHandler`1.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\HttpHandler\HttpHandler.cs:line 185
at Amazon.Runtime.Internal.RedirectHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\RedirectHandler.cs:line 59
at Amazon.Runtime.Internal.Unmarshaller.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\Unmarshaller.cs:line 85
at Amazon.S3.Internal.AmazonS3ResponseHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Services\S3\Custom\Internal\AmazonS3ResponseHandler.cs:line 58
at Amazon.Runtime.Internal.ErrorHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\ErrorHandler.cs:line 99
--- End of inner exception stack trace ---
at Amazon.Runtime.Internal.HttpErrorResponseExceptionHandler.HandleExceptionStream(IRequestContext requestContext, IWebResponseData httpErrorResponse, HttpErrorResponseException exception, Stream responseStream) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\HttpErrorResponseExceptionHandler.cs:line 163
at Amazon.Runtime.Internal.HttpErrorResponseExceptionHandler.HandleExceptionAsync(IExecutionContext executionContext, HttpErrorResponseException exception) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\HttpErrorResponseExceptionHandler.cs:line 92
at Amazon.Runtime.Internal.ExceptionHandler`1.HandleAsync(IExecutionContext executionContext, Exception exception) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\ExceptionHandler.cs:line 46
at Amazon.Runtime.Internal.ErrorHandler.ProcessExceptionAsync(IExecutionContext executionContext, Exception exception) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\ErrorHandler.cs:line 243
at Amazon.Runtime.Internal.ErrorHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\ErrorHandler.cs:line 104
at Amazon.Runtime.Internal.CallbackHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\CallbackHandler.cs:line 61
at Amazon.Runtime.Internal.Signer.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\Signer.cs:line 0
at Amazon.Runtime.Internal.EndpointDiscoveryHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\EndpointDiscoveryHandler.cs:line 75
at Amazon.Runtime.Internal.EndpointDiscoveryHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\EndpointDiscoveryHandler.cs:line 85
at Amazon.Runtime.Internal.CredentialsRetriever.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\CredentialsRetriever.cs:line 0
at Amazon.Runtime.Internal.RetryHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\RetryHandler\RetryHandler.cs:line 131
Amazon Verbose: 10004 : Single encoded /test-nonSeekable.txt with endpoint https://testbucket-issue1880.s3.us-east-2.amazonaws.com/ for canonicalization: /test-nonSeekable.txt
Amazon Verbose: 10004 : Received response (truncated to 1024 bytes): []
Amazon Error: 10002 : Part number must be an integer between 1 and 10000, inclusive, Amazon.S3.AmazonS3Exception: Part number must be an integer between 1 and 10000, inclusive
---> Amazon.Runtime.Internal.HttpErrorResponseException: Exception of type 'Amazon.Runtime.Internal.HttpErrorResponseException' was thrown.
at Amazon.Runtime.HttpWebRequestMessage.ProcessHttpResponseMessage(HttpResponseMessage responseMessage) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\HttpHandler\_netstandard\HttpRequestMessageFactory.cs:line 594
at Amazon.Runtime.HttpWebRequestMessage.GetResponseAsync(CancellationToken cancellationToken) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\HttpHandler\_netstandard\HttpRequestMessageFactory.cs:line 545
at Amazon.Runtime.Internal.HttpHandler`1.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\HttpHandler\HttpHandler.cs:line 185
at Amazon.Runtime.Internal.RedirectHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\RedirectHandler.cs:line 59
at Amazon.Runtime.Internal.Unmarshaller.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\Unmarshaller.cs:line 85
at Amazon.S3.Internal.AmazonS3ResponseHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Services\S3\Custom\Internal\AmazonS3ResponseHandler.cs:line 58
at Amazon.Runtime.Internal.ErrorHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\ErrorHandler.cs:line 99
--- End of inner exception stack trace ---
at Amazon.Runtime.Internal.HttpErrorResponseExceptionHandler.HandleExceptionStream(IRequestContext requestContext, IWebResponseData httpErrorResponse, HttpErrorResponseException exception, Stream responseStream) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\HttpErrorResponseExceptionHandler.cs:line 163
at Amazon.Runtime.Internal.HttpErrorResponseExceptionHandler.HandleExceptionAsync(IExecutionContext executionContext, HttpErrorResponseException exception) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\HttpErrorResponseExceptionHandler.cs:line 92
at Amazon.Runtime.Internal.ExceptionHandler`1.HandleAsync(IExecutionContext executionContext, Exception exception) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\ExceptionHandler.cs:line 46
at Amazon.Runtime.Internal.ErrorHandler.ProcessExceptionAsync(IExecutionContext executionContext, Exception exception) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\ErrorHandler.cs:line 243
at Amazon.Runtime.Internal.ErrorHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\ErrorHandler\ErrorHandler.cs:line 104
at Amazon.Runtime.Internal.CallbackHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\CallbackHandler.cs:line 61
at Amazon.Runtime.Internal.Signer.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\Signer.cs:line 0
at Amazon.Runtime.Internal.EndpointDiscoveryHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\EndpointDiscoveryHandler.cs:line 75
at Amazon.Runtime.Internal.EndpointDiscoveryHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\EndpointDiscoveryHandler.cs:line 85
at Amazon.Runtime.Internal.CredentialsRetriever.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\CredentialsRetriever.cs:line 0
at Amazon.Runtime.Internal.RetryHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\RetryHandler\RetryHandler.cs:line 131
at Amazon.Runtime.Internal.RetryHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\RetryHandler\RetryHandler.cs:line 146
at Amazon.Runtime.Internal.CallbackHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\CallbackHandler.cs:line 61
at Amazon.Runtime.Internal.CallbackHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\CallbackHandler.cs:line 61
at Amazon.S3.Internal.AmazonS3ExceptionHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Services\S3\Custom\Internal\AmazonS3ExceptionHandler.cs:line 57
at Amazon.Runtime.Internal.ErrorCallbackHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\ErrorCallbackHandler.cs:line 53
at Amazon.Runtime.Internal.MetricsHandler.InvokeAsync[T](IExecutionContext executionContext) in D:\source\GitHub\aws-sdk-net\sdk\src\Core\Amazon.Runtime\Pipeline\Handlers\MetricsHandler.cs:line 65
at Amazon.S3.Transfer.Internal.MultipartUploadCommand.UploadNonSeekableStreamAsync(TransferUtilityUploadRequest request, CancellationToken cancellationToken) in D:\source\GitHub\aws-sdk-net\sdk\src\Services\S3\Custom\Transfer\Internal\_async\MultipartUploadCommand.async.cs:line 243
@gunsh I've created a PR in our private repo to address this issue and it is under review. Thank you for your patience.
@gunsh The issue has been fixed in the latest version of S3 NOTE: the logged PartSize may be slightly larger than the partsize you specify on the request for unseekable stream uploads. This is because when we read the bytes from the stream, we read the bytes into a buffer, and then write those bytes to the PartBuffer. The PartBuffer's size is PART_BUFFER_SIZE + READ_BUFFER_SIZE. We add this padding to account for the case where the number of bytes we're reading from the stream is greater than the amount of bytes left in the PartBuffer.
Check the remarks in the docs about how you can tweak the read buffer as well.
Closing this issue. Feel free to reach out in case of any concerns.
Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.
Describe the bug
Please consider the scenario where a
Stream
is passed toTransferUtilityUploadRequest.InputStream
in order to callTransferUtility.UploadAsync()
. This is a custom stream that throwsNotSupportedException
in itsLength
property. This should in theory forceTransferUtility
to work with an upload of an unknown length. To help it do this correctly I setTransferUtilityUploadRequest.PartSize
to a number that is larger than the minimum 5MB but also a correct value so that the number of total parts is less or equal to 1,000 (yes, I know I can go as high as 10,000 but I deliberately chose fewer parts). Yet, when I launch such transfer I see a "Part number must be an integer between 1 and 10000, inclusive"Amazon.S3.AmazonS3Exception
.Digging through the code a bit lead me to discover that
TransferUtilityUploadRequest.PartSize
may be ignored or perhaps not used in an expected way.Expected Behavior
My expectation is for
TransferUtilityUploadRequest.PartSize
to actually be the part size of each and every of individual multi-part uploads.Current Behavior
The logs seem to indicate a different part size value is being used. See parts of the console output when
AWSConfigs.LoggingConfig.LogTo = LoggingOptions.Console
is used.Please note the calculated and set part size is "52793626". This is being output in the log but further down the line a part size of "5251072" is logged. This is obviously >10x less than what it needs to be so 10,000 parts is never enough to complete the job. Had my content been slightly smaller, I wouldn't have even noticed the issue as things would have simply worked. The "5251072" is exactly 0x502000 which is in turn also exactly
S3Constants.MinPartSize + AWSSDKUtils.DefaultBufferSize
(see this). The actual part size seems to be determined from the current position of a memory stream.Please see the redacted and truncated log from my app below.
Reproduction Steps
In order to reproduce this you must try to upload large content (more than 10,000 x 5251072 bytes) using a custom stream that does not provide
Length
.Possible Solution
No response
Additional Information/Context
No response
AWS .NET SDK and/or Package version used
AWSSDK.S3 3.7.301
Targeted .NET Platform
NET 8
Operating System and version
Both Windows 11 and Ubuntu