/******************************************************************************* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"). You may not use * this file except in compliance with the License. A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. * ***************************************************************************** * __ _ _ ___ * ( )( \/\/ )/ __) * /__\ \ / \__ \ * (_)(_) \/\/ (___/ * * AWS SDK for .NET * API Version: 2006-03-01 * */ using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Threading; using Amazon.Runtime.Internal.Util; using Amazon.S3.Model; using Amazon.S3.Transfer.Internal; using Amazon.Util; using System.Globalization; namespace Amazon.S3.Transfer { /// /// /// Provides a high level utility for managing transfers to and from Amazon S3. /// /// /// TransferUtility provides a simple API for /// uploading content to and downloading content /// from Amazon S3. It makes extensive use of Amazon S3 multipart uploads to /// achieve enhanced throughput, performance, and reliability. /// /// /// When uploading large files by specifying file paths instead of a stream, /// TransferUtility uses multiple threads to upload /// multiple parts of a single upload at once. When dealing with large content /// sizes and high bandwidth, this can increase throughput significantly. /// /// /// /// /// Transfers are stored in memory. If the application is restarted, /// previous transfers are no longer accessible. In this situation, if necessary, /// you should clean up any multipart uploads that are incomplete. /// /// public partial class TransferUtility : ITransferUtility { #region UploadDirectory /// /// Uploads files from a specified directory. /// The object key is derived from the file names /// inside the directory. /// For large uploads, the file will be divided and uploaded in parts using /// Amazon S3's multipart API. The parts will be reassembled as one object in /// Amazon S3. /// /// /// /// If you are uploading large files, TransferUtility will use multipart upload to fulfill the request. /// If a multipart upload is interrupted, TransferUtility will attempt to abort the multipart upload. /// Under certain circumstances (network outage, power failure, etc.), TransferUtility will not be able /// to abort the multipart upload. In this case, in order to stop getting charged for the storage of uploaded parts, /// you should manually invoke TransferUtility.AbortMultipartUploads() to abort the incomplete multipart uploads. /// /// /// /// The source directory, that is, the directory containing the files to upload. /// /// /// The target Amazon S3 bucket, that is, the name of the bucket to upload the files to. /// public void UploadDirectory(string directory, string bucketName) { UploadDirectoryHelper(directory, bucketName); } /// /// Uploads files from a specified directory. /// The object key is derived from the file names /// inside the directory. /// For large uploads, the file will be divided and uploaded in parts using /// Amazon S3's multipart API. The parts will be reassembled as one object in /// Amazon S3. /// /// /// /// If you are uploading large files, TransferUtility will use multipart upload to fulfill the request. /// If a multipart upload is interrupted, TransferUtility will attempt to abort the multipart upload. /// Under certain circumstances (network outage, power failure, etc.), TransferUtility will not be able /// to abort the multipart upload. In this case, in order to stop getting charged for the storage of uploaded parts, /// you should manually invoke TransferUtility.AbortMultipartUploads() to abort the incomplete multipart uploads. /// /// /// /// The source directory, that is, the directory containing the files to upload. /// /// /// The target Amazon S3 bucket, that is, the name of the bucket to upload the files to. /// /// /// A pattern used to identify the files from the source directory to upload. /// /// /// A search option that specifies whether to recursively search for files to upload /// in subdirectories. /// public void UploadDirectory(string directory, string bucketName, string searchPattern, SearchOption searchOption) { UploadDirectoryHelper(directory, bucketName, searchPattern, searchOption); } /// /// Uploads files from a specified directory. /// The object key is derived from the file names /// inside the directory. /// For large uploads, the file will be divided and uploaded in parts using /// Amazon S3's multipart API. The parts will be reassembled as one object in /// Amazon S3. /// /// /// /// If you are uploading large files, TransferUtility will use multipart upload to fulfill the request. /// If a multipart upload is interrupted, TransferUtility will attempt to abort the multipart upload. /// Under certain circumstances (network outage, power failure, etc.), TransferUtility will not be able /// to abort the multipart upload. In this case, in order to stop getting charged for the storage of uploaded parts, /// you should manually invoke TransferUtility.AbortMultipartUploads() to abort the incomplete multipart uploads. /// /// /// /// The request that contains all the parameters required to upload a directory. /// public void UploadDirectory(TransferUtilityUploadDirectoryRequest request) { UploadDirectoryHelper(request); } /// /// Initiates the asynchronous execution of the UploadDirectory operation. /// /// /// /// /// If you are uploading large files, TransferUtility will use multipart upload to fulfill the request. /// If a multipart upload is interrupted, TransferUtility will attempt to abort the multipart upload. /// Under certain circumstances (network outage, power failure, etc.), TransferUtility will not be able /// to abort the multipart upload. In this case, in order to stop getting charged for the storage of uploaded parts, /// you should manually invoke TransferUtility.AbortMultipartUploads() to abort the incomplete multipart uploads. /// /// /// /// The source directory, that is, the directory containing the files to upload. /// /// /// The target Amazon S3 bucket, that is, the name of the bucket to upload the files to. /// /// An AsyncCallback delegate that is invoked when the operation completes. /// A user-defined state object that is passed to the callback procedure. /// Retrieve this object from within the callback procedure using the AsyncState property. /// /// /// /// /// An IAsyncResult that can be used to poll, or wait for results, or both. /// This value is also needed when invoking EndUploadDirectory. public IAsyncResult BeginUploadDirectory(string directory, string bucketName, AsyncCallback callback, object state) { TransferUtilityUploadDirectoryRequest request = new TransferUtilityUploadDirectoryRequest() { BucketName = bucketName, Directory = directory }; return BeginUploadDirectory(request, callback, state); } /// /// Initiates the asynchronous execution of the UploadDirectory operation. /// /// /// /// /// If you are uploading large files, TransferUtility will use multipart upload to fulfill the request. /// If a multipart upload is interrupted, TransferUtility will attempt to abort the multipart upload. /// Under certain circumstances (network outage, power failure, etc.), TransferUtility will not be able /// to abort the multipart upload. In this case, in order to stop getting charged for the storage of uploaded parts, /// you should manually invoke TransferUtility.AbortMultipartUploads() to abort the incomplete multipart uploads. /// /// /// /// The source directory, that is, the directory containing the files to upload. /// /// /// The target Amazon S3 bucket, that is, the name of the bucket to upload the files to. /// /// /// A pattern used to identify the files from the source directory to upload. /// /// /// A search option that specifies whether to recursively search for files to upload /// in subdirectories. /// /// An AsyncCallback delegate that is invoked when the operation completes. /// A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the AsyncState property. /// /// /// /// An IAsyncResult that can be used to poll, or wait for results, or both. /// This value is also needed when invoking EndUploadDirectory. public IAsyncResult BeginUploadDirectory(string directory, string bucketName, string searchPattern, SearchOption searchOption, AsyncCallback callback, object state) { TransferUtilityUploadDirectoryRequest request = new TransferUtilityUploadDirectoryRequest() { BucketName = bucketName, Directory = directory, SearchPattern = searchPattern, SearchOption = searchOption }; return BeginUploadDirectory(request, callback, state); } /// /// Initiates the asynchronous execution of the UploadDirectory operation. /// /// /// /// /// If you are uploading large files, TransferUtility will use multipart upload to fulfill the request. /// If a multipart upload is interrupted, TransferUtility will attempt to abort the multipart upload. /// Under certain circumstances (network outage, power failure, etc.), TransferUtility will not be able /// to abort the multipart upload. In this case, in order to stop getting charged for the storage of uploaded parts, /// you should manually invoke TransferUtility.AbortMultipartUploads() to abort the incomplete multipart uploads. /// /// /// /// The request that contains all the parameters required to upload a directory. /// /// An AsyncCallback delegate that is invoked when the operation completes. /// A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the AsyncState property. /// /// /// /// An IAsyncResult that can be used to poll, or wait for results, or both. /// This value is also needed when invoking EndUploadDirectory. public IAsyncResult BeginUploadDirectory(TransferUtilityUploadDirectoryRequest request, AsyncCallback callback, object state) { validate(request); UploadDirectoryCommand command = new UploadDirectoryCommand(this, this._config, request); return beginOperation(command, callback, state); } /// /// Finishes the asynchronous execution of the UploadDirectory operation. /// /// /// The IAsyncResult returned by the call to BeginUploadDirectory. /// /// /// public void EndUploadDirectory(IAsyncResult asyncResult) { endOperation(asyncResult); } #endregion #region Upload /// /// Uploads the specified file. /// The object key is derived from the file's name. /// Multiple threads are used to read the file and perform multiple uploads in parallel. /// For large uploads, the file will be divided and uploaded in parts using /// Amazon S3's multipart API. The parts will be reassembled as one object in /// Amazon S3. /// /// /// /// If you are uploading large files, TransferUtility will use multipart upload to fulfill the request. /// If a multipart upload is interrupted, TransferUtility will attempt to abort the multipart upload. /// Under certain circumstances (network outage, power failure, etc.), TransferUtility will not be able /// to abort the multipart upload. In this case, in order to stop getting charged for the storage of uploaded parts, /// you should manually invoke TransferUtility.AbortMultipartUploads() to abort the incomplete multipart uploads. /// /// /// /// The file path of the file to upload. /// /// /// The target Amazon S3 bucket, that is, the name of the bucket to upload the file to. /// public void Upload(string filePath, string bucketName) { UploadHelper(filePath, bucketName); } /// /// Uploads the specified file. /// Multiple threads are used to read the file and perform multiple uploads in parallel. /// For large uploads, the file will be divided and uploaded in parts using /// Amazon S3's multipart API. The parts will be reassembled as one object in /// Amazon S3. /// /// /// /// If you are uploading large files, TransferUtility will use multipart upload to fulfill the request. /// If a multipart upload is interrupted, TransferUtility will attempt to abort the multipart upload. /// Under certain circumstances (network outage, power failure, etc.), TransferUtility will not be able /// to abort the multipart upload. In this case, in order to stop getting charged for the storage of uploaded parts, /// you should manually invoke TransferUtility.AbortMultipartUploads() to abort the incomplete multipart uploads. /// /// /// /// The file path of the file to upload. /// /// /// The target Amazon S3 bucket, that is, the name of the bucket to upload the file to. /// /// /// The key under which the Amazon S3 object is stored. /// public void Upload(string filePath, string bucketName, string key) { UploadHelper(filePath, bucketName, key); } /// /// Uploads the contents of the specified stream. /// For large uploads, the file will be divided and uploaded in parts using /// Amazon S3's multipart API. The parts will be reassembled as one object in /// Amazon S3. /// /// /// /// If you are uploading large files, TransferUtility will use multipart upload to fulfill the request. /// If a multipart upload is interrupted, TransferUtility will attempt to abort the multipart upload. /// Under certain circumstances (network outage, power failure, etc.), TransferUtility will not be able /// to abort the multipart upload. In this case, in order to stop getting charged for the storage of uploaded parts, /// you should manually invoke TransferUtility.AbortMultipartUploads() to abort the incomplete multipart uploads. /// /// /// /// The stream to read to obtain the content to upload. /// /// /// The target Amazon S3 bucket, that is, the name of the bucket to upload the stream to. /// /// /// The key under which the Amazon S3 object is stored. /// public void Upload(Stream stream, string bucketName, string key) { UploadHelper(stream, bucketName, key); } /// /// Uploads the file or stream specified by the request. /// To track the progress of the upload, /// add an event listener to the request's UploadProgressEvent. /// For large uploads, the file will be divided and uploaded in parts using /// Amazon S3's multipart API. The parts will be reassembled as one object in /// Amazon S3. /// /// /// /// If you are uploading large files, TransferUtility will use multipart upload to fulfill the request. /// If a multipart upload is interrupted, TransferUtility will attempt to abort the multipart upload. /// Under certain circumstances (network outage, power failure, etc.), TransferUtility will not be able /// to abort the multipart upload. In this case, in order to stop getting charged for the storage of uploaded parts, /// you should manually invoke TransferUtility.AbortMultipartUploads() to abort the incomplete multipart uploads. /// /// /// /// Contains all the parameters required to upload to Amazon S3. /// public void Upload(TransferUtilityUploadRequest request) { this.UploadHelper(request); } /// /// Initiates the asynchronous execution of the Upload operation. /// /// /// /// /// If you are uploading large files, TransferUtility will use multipart upload to fulfill the request. /// If a multipart upload is interrupted, TransferUtility will attempt to abort the multipart upload. /// Under certain circumstances (network outage, power failure, etc.), TransferUtility will not be able /// to abort the multipart upload. In this case, in order to stop getting charged for the storage of uploaded parts, /// you should manually invoke TransferUtility.AbortMultipartUploads() to abort the incomplete multipart uploads. /// /// /// /// The file path of the file to upload. /// /// /// The target Amazon S3 bucket, that is, the name of the bucket to upload the file to. /// /// An AsyncCallback delegate that is invoked when the operation completes. /// A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the AsyncState property. /// /// /// /// An IAsyncResult that can be used to poll, or wait for results, or both. /// This values is also needed when invoking EndUpload. public IAsyncResult BeginUpload(string filePath, string bucketName, AsyncCallback callback, object state) { if (string.IsNullOrEmpty(filePath)) { throw new ArgumentNullException("filePath"); } if (!File.Exists(filePath)) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The file {0} does not exists!", filePath)); } TransferUtilityUploadRequest request = new TransferUtilityUploadRequest() { BucketName = bucketName, FilePath = filePath }; return BeginUpload(request, callback, state); } /// /// Initiates the asynchronous execution of the Upload operation. /// /// /// /// /// If you are uploading large files, TransferUtility will use multipart upload to fulfill the request. /// If a multipart upload is interrupted, TransferUtility will attempt to abort the multipart upload. /// Under certain circumstances (network outage, power failure, etc.), TransferUtility will not be able /// to abort the multipart upload. In this case, in order to stop getting charged for the storage of uploaded parts, /// you should manually invoke TransferUtility.AbortMultipartUploads() to abort the incomplete multipart uploads. /// /// /// /// The file path of the file to upload. /// /// /// The target Amazon S3 bucket, that is, the name of the bucket to upload the file to. /// /// /// The key under which the Amazon S3 object is stored. /// /// An AsyncCallback delegate that is invoked when the operation completes. /// A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the AsyncState property. /// /// /// /// An IAsyncResult that can be used to poll, or wait for results, or both. /// This values is also needed when invoking EndUpload. public IAsyncResult BeginUpload(string filePath, string bucketName, string key, AsyncCallback callback, object state) { if (string.IsNullOrEmpty(filePath)) { throw new ArgumentNullException("filePath"); } if (!File.Exists(filePath)) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The file {0} does not exists!", filePath)); } TransferUtilityUploadRequest request = new TransferUtilityUploadRequest() { BucketName = bucketName, Key = key, FilePath = filePath }; return BeginUpload(request, callback, state); } /// /// Initiates the asynchronous execution of the Upload operation. /// /// /// /// /// If you are uploading large files, TransferUtility will use multipart upload to fulfill the request. /// If a multipart upload is interrupted, TransferUtility will attempt to abort the multipart upload. /// Under certain circumstances (network outage, power failure, etc.), TransferUtility will not be able /// to abort the multipart upload. In this case, in order to stop getting charged for the storage of uploaded parts, /// you should manually invoke TransferUtility.AbortMultipartUploads() to abort the incomplete multipart uploads. /// /// /// /// The stream to read to obtain the content to upload. /// /// /// The target Amazon S3 bucket, that is, the name of the bucket to upload the stream to. /// /// /// The key under which the Amazon S3 object is stored. /// /// An AsyncCallback delegate that is invoked when the operation completes. /// A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the AsyncState property. /// /// /// /// An IAsyncResult that can be used to poll, or wait for results, or both. /// This values is also needed when invoking EndUpload. public IAsyncResult BeginUpload(Stream stream, string bucketName, string key, AsyncCallback callback, object state) { if (stream == null) { throw new ArgumentNullException("stream"); } if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } TransferUtilityUploadRequest request = new TransferUtilityUploadRequest() { BucketName = bucketName, Key = key, InputStream = stream }; return BeginUpload(request, callback, state); } /// /// Initiates the asynchronous execution of the Upload operation. /// /// /// /// /// If you are uploading large files, TransferUtility will use multipart upload to fulfill the request. /// If a multipart upload is interrupted, TransferUtility will attempt to abort the multipart upload. /// Under certain circumstances (network outage, power failure, etc.), TransferUtility will not be able /// to abort the multipart upload. In this case, in order to stop getting charged for the storage of uploaded parts, /// you should manually invoke TransferUtility.AbortMultipartUploads() to abort the incomplete multipart uploads. /// /// /// /// Contains all the parameters required to upload to Amazon S3. /// /// An AsyncCallback delegate that is invoked when the operation completes. /// A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the AsyncState property. /// /// /// /// An IAsyncResult that can be used to poll, or wait for results, or both. /// This values is also needed when invoking EndUpload. public IAsyncResult BeginUpload(TransferUtilityUploadRequest request, AsyncCallback callback, object state) { validate(request); BaseCommand command; if (request.ContentLength < this._config.MinSizeBeforePartUpload) { command = new SimpleUploadCommand(this._s3Client, this._config, request); } else { command = new MultipartUploadCommand(this._s3Client, this._config, request); } return beginOperation(command, callback, state); } /// /// Finishes the asynchronous execution of the Upload operation. /// /// /// The IAsyncResult returned by the call to BeginUpload. /// /// /// public void EndUpload(IAsyncResult asyncResult) { endOperation(asyncResult); } #endregion #region OpenStream /// /// Returns a stream from which the caller can read the content from the specified /// Amazon S3 bucket and key. /// The caller of this method is responsible for closing the stream. /// /// /// The name of the bucket. /// /// /// The object key. /// /// /// A stream of the contents from the specified Amazon S3 and key. /// public Stream OpenStream(string bucketName, string key) { return OpenStreamHelper(bucketName, key); } /// /// Returns a stream to read the contents from Amazon S3 as /// specified by the TransferUtilityOpenStreamRequest. /// The caller of this method is responsible for closing the stream. /// /// /// Contains all the parameters required to open a stream to an S3 object. /// /// /// A stream of the contents from Amazon S3. /// public Stream OpenStream(TransferUtilityOpenStreamRequest request) { return OpenStreamHelper(request); } /// /// Initiates the asynchronous execution of the OpenStream operation. /// /// /// /// The name of the bucket. /// /// /// The object key. /// /// An AsyncCallback delegate that is invoked when the operation completes. /// A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the AsyncState property. /// /// /// /// An IAsyncResult that can be used to poll, or wait for results, or both. /// This values is also needed when invoking EndOpenStream. public IAsyncResult BeginOpenStream(string bucketName, string key, AsyncCallback callback, object state) { TransferUtilityOpenStreamRequest request = new TransferUtilityOpenStreamRequest() { BucketName = bucketName, Key = key }; return BeginOpenStream(request, callback, state); } /// /// Initiates the asynchronous execution of the OpenStream operation. /// /// /// /// Contains all the parameters required to open a stream to an Amazon S3 object. /// /// An AsyncCallback delegate that is invoked when the operation completes. /// A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the AsyncState property. /// /// /// /// An IAsyncResult that can be used to poll, or wait for results, or both. /// This values is also needed when invoking EndOpenStream. public IAsyncResult BeginOpenStream(TransferUtilityOpenStreamRequest request, AsyncCallback callback, object state) { OpenStreamCommand command = new OpenStreamCommand(this._s3Client, request); return beginOperation(command, callback, state); } /// /// Finishes the asynchronous execution of the OpenStream operation. /// /// /// The IAsyncResult returned by the call to BeginOpenStream. /// /// /// public Stream EndOpenStream(IAsyncResult asyncResult) { return endOperation(asyncResult) as Stream; } #endregion #region Download /// /// Downloads the content from Amazon S3 and writes it to the specified file. /// /// /// The file path where the content from Amazon S3 will be written to. /// /// /// The name of the bucket containing the Amazon S3 object to download. /// /// /// The key under which the Amazon S3 object is stored. /// public void Download(string filePath, string bucketName, string key) { DownloadHelper(filePath, bucketName, key); } /// /// Downloads the content from Amazon S3 and writes it to the specified file. /// If the key is not specified in the request parameter, /// the file name will used as the key name. /// /// /// Contains all the parameters required to download an Amazon S3 object. /// public void Download(TransferUtilityDownloadRequest request) { DownloadHelper(request); } /// /// Initiates the asynchronous execution of the Download operation. /// /// /// /// The file path where the content from Amazon S3 will be written to. /// /// /// The name of the bucket containing the Amazon S3 object to download. /// /// /// The key under which the Amazon S3 object is stored. /// /// An AsyncCallback delegate that is invoked when the operation completes. /// A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the AsyncState property. /// /// /// /// An IAsyncResult that can be used to poll, or wait for results, or both. /// This values is also needed when invoking EndDownload. public IAsyncResult BeginDownload(string filePath, string bucketName, string key, AsyncCallback callback, object state) { TransferUtilityDownloadRequest request = new TransferUtilityDownloadRequest() { BucketName = bucketName, Key = key, FilePath = filePath }; return BeginDownload(request, callback, state); } /// /// Initiates the asynchronous execution of the Download operation. /// /// /// /// Contains all the parameters required to download an Amazon S3 object. /// /// An AsyncCallback delegate that is invoked when the operation completes. /// A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the AsyncState property. /// /// /// /// An IAsyncResult that can be used to poll, or wait for results, or both. /// This values is also needed when invoking EndDownload. public IAsyncResult BeginDownload(TransferUtilityDownloadRequest request, AsyncCallback callback, object state) { BaseCommand command = new DownloadCommand(this._s3Client, request); return beginOperation(command, callback, state); } /// /// Finishes the asynchronous execution of the Download operation. /// /// /// The IAsyncResult returned by the call to BeginDownload. /// /// /// public void EndDownload(IAsyncResult asyncResult) { endOperation(asyncResult); } #endregion #region DownloadDirectory /// /// Downloads the objects in Amazon S3 that have a key that starts with the value /// specified by s3Directory. /// /// /// The name of the bucket containing the Amazon S3 objects to download. /// /// /// The directory in Amazon S3 to download. /// /// /// The local directory to download the objects to. /// public void DownloadDirectory(string bucketName, string s3Directory, string localDirectory) { DownloadDirectoryHelper(bucketName, s3Directory, localDirectory); } /// /// Downloads the objects in Amazon S3 that have a key that starts with the value /// specified by the S3Directory /// property of the passed in TransferUtilityDownloadDirectoryRequest object. /// /// /// Contains all the parameters required to download objects from Amazon S3 /// into a local directory. /// public void DownloadDirectory(TransferUtilityDownloadDirectoryRequest request) { DownloadDirectoryHelper(request); } /// /// Initiates the asynchronous execution of the DownloadDirectory operation. /// /// /// /// The name of the bucket containing the Amazon S3 objects to download. /// /// /// The directory in Amazon S3 to download. /// /// /// The local directory to download the objects to. /// /// An AsyncCallback delegate that is invoked when the operation completes. /// A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the AsyncState property. /// /// /// /// An IAsyncResult that can be used to poll, or wait for results, or both. /// This values is also needed when invoking EndDownloadDirectory. public IAsyncResult BeginDownloadDirectory(string bucketName, string s3Directory, string localDirectory, AsyncCallback callback, object state) { TransferUtilityDownloadDirectoryRequest request = new TransferUtilityDownloadDirectoryRequest() { BucketName = bucketName, S3Directory = s3Directory, LocalDirectory = localDirectory }; return BeginDownloadDirectory(request, callback, state); } /// /// Initiates the asynchronous execution of the DownloadDirectory operation. /// /// /// /// Contains all the parameters required to download objects from a directory in Amazon S3 /// to a local directory. /// /// An AsyncCallback delegate that is invoked when the operation completes. /// A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the AsyncState property. /// /// /// /// An IAsyncResult that can be used to poll, or wait for results, or both. /// This values is also needed when invoking EndDownload. public IAsyncResult BeginDownloadDirectory(TransferUtilityDownloadDirectoryRequest request, AsyncCallback callback, object state) { BaseCommand command = new DownloadDirectoryCommand(this._s3Client, request); return beginOperation(command, callback, state); } /// /// Finishes the asynchronous execution of the DownloadDirectory operation. /// /// /// The IAsyncResult returned by the call to BeginDownloadDirectory. /// /// /// public void EndDownloadDirectory(IAsyncResult asyncResult) { endOperation(asyncResult); } #endregion #region AbortMultipartUploads /// /// Aborts the multipart uploads that were initiated before the specified date. /// /// /// The name of the bucket containing multipart uploads. /// /// /// The date before which the multipart uploads were initiated. /// public void AbortMultipartUploads(string bucketName, DateTime initiatedDate) { AbortMultipartUploadsHelper(bucketName, initiatedDate); } /// /// Initiates the asynchronous execution of the AbortMultipartUploads operation. /// /// /// /// The name of the bucket containing multipart uploads. /// /// /// The date before which the multipart uploads were initiated. /// /// An AsyncCallback delegate that is invoked when the operation completes. /// A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the AsyncState property. /// /// /// /// An IAsyncResult that can be used to poll, or wait for results, or both. /// This values is also needed when invoking EndAbortMultipartUploads. public IAsyncResult BeginAbortMultipartUploads(string bucketName, DateTime initiatedDate, AsyncCallback callback, object state) { BaseCommand command = new AbortMultipartUploadsCommand(this._s3Client, bucketName, initiatedDate); return beginOperation(command, callback, state); } /// /// Finishes the asynchronous execution of the AbortMultipartUploads operation. /// /// /// The IAsyncResult returned by the call to BeginAbortMultipartUploads. /// /// /// public void EndAbortMultipartUploads(IAsyncResult asyncResult) { endOperation(asyncResult); } #endregion #region UploadDirectory helper methods private void UploadDirectoryHelper(string directory, string bucketName) { var request = ConstructUploadDirectoryRequest(directory, bucketName); UploadDirectoryHelper(request); } private void UploadDirectoryHelper(string directory, string bucketName, string searchPattern, SearchOption searchOption) { var request = ConstructUploadDirectoryRequest(directory, bucketName, searchPattern, searchOption); UploadDirectoryHelper(request); } private void UploadDirectoryHelper(TransferUtilityUploadDirectoryRequest request) { CheckForBlockedArn(request.BucketName, "UploadDirectory"); validate(request); UploadDirectoryCommand command = new UploadDirectoryCommand(this, this._config, request); command.Execute(); } #endregion #region Upload helper methods private void UploadHelper(string filePath, string bucketName) { var request = ConstructUploadRequest(filePath, bucketName); UploadHelper(request); } /// /// Uploads the specified file. /// Multiple threads are used to read the file and perform multiple uploads in parallel. /// For large uploads, the file will be divided and uploaded in parts using /// Amazon S3's multipart API. The parts will be reassembled as one object in /// Amazon S3. /// /// /// The file path of the file to upload. /// /// /// The target Amazon S3 bucket, that is, the name of the bucket to upload the file to. /// /// /// The key under which the Amazon S3 object is stored. /// private void UploadHelper(string filePath, string bucketName, string key) { var request = ConstructUploadRequest(filePath, bucketName, key); UploadHelper(request); } /// /// Uploads the contents of the specified stream. /// For large uploads, the file will be divided and uploaded in parts using /// Amazon S3's multipart API. The parts will be reassembled as one object in /// Amazon S3. /// /// /// The stream to read to obtain the content to upload. /// /// /// The target Amazon S3 bucket, that is, the name of the bucket to upload the stream to. /// /// /// The key under which the Amazon S3 object is stored. /// private void UploadHelper(Stream stream, string bucketName, string key) { var request = ConstructUploadRequest(stream, bucketName, key); UploadHelper(request); } /// /// Uploads the file or stream specified by the request. /// To track the progress of the upload, /// add an event listener to the request's UploadProgressEvent. /// For large uploads, the file will be divided and uploaded in parts using /// Amazon S3's multipart API. The parts will be reassembled as one object in /// Amazon S3. /// /// /// Contains all the parameters required to upload to Amazon S3. /// private void UploadHelper(TransferUtilityUploadRequest request) { CheckForBlockedArn(request.BucketName, "Upload"); var command = GetUploadCommand(request); command.Execute(); } #endregion #region OpenStream helper methods private Stream OpenStreamHelper(string bucketName, string key) { TransferUtilityOpenStreamRequest request = new TransferUtilityOpenStreamRequest() { BucketName = bucketName, Key = key }; return OpenStreamHelper(request); } private Stream OpenStreamHelper(TransferUtilityOpenStreamRequest request) { CheckForBlockedArn(request.BucketName, "OpenStream"); OpenStreamCommand command = new OpenStreamCommand(this._s3Client, request); command.Execute(); return command.ResponseStream; } #endregion #region Download helper methods private void DownloadHelper(string filePath, string bucketName, string key) { TransferUtilityDownloadRequest request = ConstructDownloadRequest(filePath, bucketName, key); DownloadHelper(request); } private void DownloadHelper(TransferUtilityDownloadRequest request) { CheckForBlockedArn(request.BucketName, "Download"); BaseCommand command = new DownloadCommand(this._s3Client, request); command.Execute(); } #endregion #region DownloadDirectory helper methods private void DownloadDirectoryHelper(string bucketName, string s3Directory, string localDirectory) { var request = ConstructDownloadDirectoryRequest(bucketName, s3Directory, localDirectory); DownloadDirectoryHelper(request); } private void DownloadDirectoryHelper(TransferUtilityDownloadDirectoryRequest request) { CheckForBlockedArn(request.BucketName, "DownloadDirectory"); BaseCommand command = new DownloadDirectoryCommand(this._s3Client, request); command.Execute(); } #endregion #region AbortMultipartUploads helper methods private void AbortMultipartUploadsHelper(string bucketName, DateTime initiatedDate) { CheckForBlockedArn(bucketName, "AbortMultipartUploads"); BaseCommand command = new AbortMultipartUploadsCommand(this._s3Client, bucketName, initiatedDate); command.Execute(); } #endregion #region Private Methods static IAsyncResult beginOperation(BaseCommand command, AsyncCallback callback, object state) { Executer exe = new Executer(callback, state, command); ThreadPool.QueueUserWorkItem(s => exe.Execute()); return exe.AsyncResult; } static object endOperation(IAsyncResult result) { TransferAsyncResult transferAsyncResult = result as TransferAsyncResult; if (transferAsyncResult == null) return null; using (transferAsyncResult) { if (!transferAsyncResult.CompletedSynchronously) { WaitHandle.WaitAll(new WaitHandle[] { transferAsyncResult.AsyncWaitHandle }); } if (transferAsyncResult.LastException != null) { AWSSDKUtils.PreserveStackTrace(transferAsyncResult.LastException); throw transferAsyncResult.LastException; } return transferAsyncResult.Return; } } #endregion } internal class Executer { TransferAsyncResult _asyncResult; BaseCommand _command; private Executer(TransferAsyncResult asyncResult, BaseCommand command) { this._asyncResult = asyncResult; this._command = command; } internal Executer(AsyncCallback callback, object state, BaseCommand command) : this(new TransferAsyncResult(callback, state), command) { } internal void Execute() { try { this._command.Execute(); this._asyncResult.Return = this._command.Return; } catch (Exception e) { this._asyncResult.LastException = e; } finally { this._asyncResult.SignalWaitHandle(); if (this._asyncResult.Callback != null) { this._asyncResult.Callback(this._asyncResult); } } } internal TransferAsyncResult AsyncResult { get { return _asyncResult; } } } internal class TransferAsyncResult : IAsyncResult, IDisposable { AsyncCallback _callback; object _state; bool _isComplete; ManualResetEvent _waitHandle; Exception _lastException; object _return; bool _disposed = false; internal TransferAsyncResult(AsyncCallback callback, object state) { this._callback = callback; this._state = state; this._waitHandle = new ManualResetEvent(false); } public bool CompletedSynchronously { get { return false; } } public bool IsCompleted { get { return this._isComplete; } } public object AsyncState { get { return this._state; } } public WaitHandle AsyncWaitHandle { get { return this._waitHandle; } } internal void SignalWaitHandle() { this._isComplete = true; this._waitHandle.Set(); } internal AsyncCallback Callback { get { return this._callback; } } internal Exception LastException { get { return this._lastException; } set { this._lastException = value; } } internal object Return { get { return this._return; } set { this._return = value; } } #region Dispose Pattern Implementation /// /// Implements the Dispose pattern /// /// Whether this object is being disposed via a call to Dispose /// or garbage collected. protected virtual void Dispose(bool disposing) { if (!this._disposed) { if (disposing && _waitHandle != null) { _waitHandle.Close(); _waitHandle = null; } this._disposed = true; } } /// /// Disposes of all managed and unmanaged resources. /// public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } #endregion } }