/*
* 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.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Amazon.Runtime.Internal.Util;
using Amazon.S3.Model;
using Amazon.S3.Transfer.Internal;
using Amazon.Util;
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 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.AbortMultipartUploadsAsync() 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.
///
///
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
///
/// The task object representing the asynchronous operation.
public Task UploadAsync(string filePath, string bucketName, CancellationToken cancellationToken = default(CancellationToken))
{
var request = ConstructUploadRequest(filePath, bucketName);
return UploadAsync(request, cancellationToken);
}
///
/// 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.AbortMultipartUploadsAsync() 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.
///
///
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
///
/// The task object representing the asynchronous operation.
public Task UploadAsync(string filePath, string bucketName, string key, CancellationToken cancellationToken = default(CancellationToken))
{
var request = ConstructUploadRequest(filePath, bucketName,key);
return UploadAsync(request, cancellationToken);
}
///
/// 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.AbortMultipartUploadsAsync() 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.
///
///
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
///
/// The task object representing the asynchronous operation.
public Task UploadAsync(Stream stream, string bucketName, string key, CancellationToken cancellationToken = default(CancellationToken))
{
var request = ConstructUploadRequest(stream, bucketName, key);
return UploadAsync(request, cancellationToken);
}
///
/// 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.AbortMultipartUploadsAsync() to abort the incomplete multipart uploads.
///
///
///
/// Contains all the parameters required to upload to Amazon S3.
///
///
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
///
/// The task object representing the asynchronous operation.
public Task UploadAsync(TransferUtilityUploadRequest request, CancellationToken cancellationToken = default(CancellationToken))
{
CheckForBlockedArn(request.BucketName, "Upload");
var command = GetUploadCommand(request, null);
return command.ExecuteAsync(cancellationToken);
}
#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.
///
///
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
///
/// The task object representing the asynchronous operation.
public Task AbortMultipartUploadsAsync(string bucketName, DateTime initiatedDate, CancellationToken cancellationToken = default(CancellationToken))
{
CheckForBlockedArn(bucketName, "AbortMultipartUploads");
var command = new AbortMultipartUploadsCommand(this._s3Client, bucketName, initiatedDate, this._config);
return command.ExecuteAsync(cancellationToken);
}
#endregion
#region Download
///
/// 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.
///
///
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
///
/// The task object representing the asynchronous operation.
public Task DownloadAsync(TransferUtilityDownloadRequest request, CancellationToken cancellationToken = default(CancellationToken))
{
CheckForBlockedArn(request.BucketName, "Download");
var command = new DownloadCommand(this._s3Client, request);
return command.ExecuteAsync(cancellationToken);
}
#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 cancellation token that can be used by other objects or threads to receive notice of cancellation.
///
/// The task object representing the asynchronous operation.
public Task OpenStreamAsync(string bucketName, string key, CancellationToken cancellationToken = default(CancellationToken))
{
TransferUtilityOpenStreamRequest request = new TransferUtilityOpenStreamRequest()
{
BucketName = bucketName,
Key = key
};
return OpenStreamAsync(request, cancellationToken);
}
///
/// 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 for the OpenStream operation.
///
///
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
///
/// The task object representing the asynchronous operation.
public async Task OpenStreamAsync(TransferUtilityOpenStreamRequest request, CancellationToken cancellationToken = default(CancellationToken))
{
CheckForBlockedArn(request.BucketName, "OpenStream");
OpenStreamCommand command = new OpenStreamCommand(this._s3Client, request);
await command.ExecuteAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
return command.ResponseStream;
}
#endregion
internal BaseCommand GetUploadCommand(TransferUtilityUploadRequest request, SemaphoreSlim asyncThrottler)
{
validate(request);
if (IsMultipartUpload(request))
{
var command = new MultipartUploadCommand(this._s3Client, this._config, request);
command.AsyncThrottler = asyncThrottler;
return command;
}
else
{
var command = new SimpleUploadCommand(this._s3Client, this._config, request);
command.AsyncThrottler = asyncThrottler;
return command;
}
}
}
}