I am using the latest version of the official Amazon S3 SDK (1.0.14.1) to create a backup tool. So far everything works correctly if the size of the file I'm uploading is below 5 MB, but when any of the files is above 5 MB the upload fails with the following exception:
System.Net.WebException: The request was aborted: The request was canceled. ---> System.IO.IOException: Cannot close stream until all bytes are written. at System.Net.ConnectStream.CloseInternal(Boolean internalCall, Boolean aborting) --- End of inner exception stack trace --- at Amazon.S3.AmazonS3Client.ProcessRequestError(String actionName, HttpWebRequest request, WebException we, HttpWebResponse errorResponse, String requestAddr, WebHeaderCollection& respHdrs, Type t) at Amazon.S3.AmazonS3Client.Invoke[T](S3Request userRequest) at Amazon.S3.AmazonS3Client.PutObject(PutObjectRequest request) at BackupToolkit.S3Module.UploadFile(String sourceFileName, String destinationFileName) in W:\code\AutoBackupTool\BackupToolkit\S3Module.cs:line 88 at BackupToolkit.S3Module.UploadFiles(String sourceDirectory) in W:\code\AutoBackupTool\BackupToolkit\S3Module.cs:line 108
Note: 5 MB is roughly the boundary of failure, it can be slightly lower or anything higher
I am assuming that the connection is timing out and the stream is being automatically closed before the file upload completes.
I've tried to find a way to set a long timeout (but I can't find the option in either AmazonS3 or AmazonS3Config). 
Any ideas on how to increase the time-out (like an application wide setting I can use) or is it unrelated to a timeout issue?
Code:
var s3Client = AWSClientFactory.CreateAmazonS3Client(AwsAccessKey, AwsSecretKey);  var putObjectRequest = new PutObjectRequest {      BucketName            = Bucket,     FilePath              = sourceFileName,     Key                   = destinationFileName,     MD5Digest             = md5Base64,     GenerateMD5Digest     = true };  using (var upload = s3Client.PutObject(putObjectRequest)) {  } Instead of using the Amazon S3 console, try uploading the file using the AWS Command Line Interface (AWS CLI) or an AWS SDK. Note: If you use the Amazon S3 console, the maximum file size for uploads is 160 GB. To upload a file that is larger than 160 GB, use the AWS CLI, AWS SDK, or Amazon S3 REST API.
Individual Amazon S3 objects can range in size from a minimum of 0 bytes to a maximum of 5 TB. The largest object that can be uploaded in a single PUT is 5 GB. For objects larger than 100 MB, customers should consider using the Multipart Upload capability.
Maximum is 5 TB . In single PUT, Max is 5 gb.
Individual Amazon S3 objects can range in size from a minimum of 0 bytes to a maximum of 5 terabytes. The largest object that can be uploaded in a single PUT is 5 gigabytes.
Updated answer:
I recently updated one of my projects that uses the Amazon AWS .NET SDK (to version 1.4.1.0) and in this version there are two improvements that did not exist when I wrote the original answer here.
Timeout to -1 to have an infinite time limit for the put operation.PutObjectRequest called ReadWriteTimeout which can be set (in milliseconds) to timeout on the stream read/write level opposed to the entire put operation level.So my code now looks like this:
var putObjectRequest = new PutObjectRequest {      BucketName            = Bucket,     FilePath              = sourceFileName,     Key                   = destinationFileName,     MD5Digest             = md5Base64,     GenerateMD5Digest     = true,     Timeout               = -1,     ReadWriteTimeout      = 300000     // 5 minutes in milliseconds }; Original answer:
I managed to figure out the answer...
Before posting the question I had explored AmazonS3 and AmazonS3Config but not PutObjectRequest.
Inside PutObjectRequest there is a Timeout property (set in milliseconds).  I have successfully used this to upload the larger files (note: setting it to 0 doesn't remove the timeout, you need to specify a positive number of miliseconds... I've gone for 1 hour).
This works fine:
var putObjectRequest = new PutObjectRequest {      BucketName            = Bucket,     FilePath              = sourceFileName,     Key                   = destinationFileName,     MD5Digest             = md5Base64,     GenerateMD5Digest     = true,     Timeout               = 3600000 }; I've been having similar problems to this and started to use the TransferUtility class to perform multi part uploads.
At the moment this code is working. I did have problems when the timeout was set too low though!
                var request = new TransferUtilityUploadRequest()                 .WithBucketName(BucketName)                 .WithFilePath(sourceFile.FullName)                 .WithKey(key)                 .WithTimeout(100 * 60 * 60 * 1000)                 .WithPartSize(10 * 1024 * 1024)                 .WithSubscriber((src, e) =>                 {                     Console.CursorLeft = 0;                     Console.Write("{0}: {1} of {2}    ", sourceFile.Name, e.TransferredBytes, e.TotalBytes);                 });             utility.Upload(request); As I'm typing this, I have a 4GB upload taking place and it's already got further through than ever before!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With