modules/AWSPowerShell/Cmdlets/S3/Advanced/Read-S3Object-Cmdlet.cs (23 lines of code) (raw):
/*******************************************************************************
* 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 Tools for Windows (TM) PowerShell (TM)
*
*/
using System;
using System.Linq;
using System.Management.Automation;
using Amazon.PowerShell.Common;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.S3.Transfer;
using System.IO;
using Amazon.PowerShell.Utils;
namespace Amazon.PowerShell.Cmdlets.S3
{
/// <summary>
/// <para>
/// Downloads an S3 object, optionally including sub-objects, to a local file or folder location. Returns a
/// FileInfo or DirectoryInfo instance to the downloaded file or the containing folder.
/// </para>
/// <para>
/// Note that you can pipe an Amazon.S3.Model.S3Object instance to this cmdlet and its members will be used to
/// satisfy the BucketName, Key and optionally VersionId (if an S3ObjectVersion instance is supplied), parameters.
/// </para>
/// </summary>
[Cmdlet("Read", "S3Object", DefaultParameterSetName = ParamSet_ToLocalFile)]
[OutputType(new Type[] { typeof(System.IO.FileInfo), typeof(System.IO.DirectoryInfo) })]
[AWSCmdlet("Downloads one or more objects from an S3 bucket to the local file system.", Operation = new[] { "GetObject" })]
[AWSCmdletOutput("System.IO.FileInfo instance if reading a single object or System.IO.DirectoryInfo instance for multi-object read.",
"Returns a System.IO.FileInfo instance representing the local file if reading a single object or a System.IO.DirectoryInfo instance to the root parent folder if reading multiple objects."
)]
public class ReadS3ObjectCmdlet : AmazonS3ClientCmdlet, IExecutor
{
const string ParamSet_ToLocalFile = "DownloadFile";
const string ParamSet_ToLocalFolder = "DownloadFolder";
const string ParamSet_FromS3Object = "FromS3ObjectToFileOrFolder";
// try and anticipate all the ways a user might mean 'get everything from root'
internal static readonly string[] rootIndicators = new string[] { "/", @"\", "*", "/*", @"\*" };
protected override bool IsSensitiveRequest { get; set; } = true;
#region Bucket Params
#region Parameter BucketName
/// <summary>
/// <para>
/// Name of the bucket that holds the content to be downloaded.
/// </para>
///
/// <para>
/// <b>Directory buckets</b> - When you use this operation with a directory bucket, you
/// must use virtual-hosted-style requests in the format <c> <i>Bucket_name</i>.s3express-<i>az_id</i>.<i>region</i>.amazonaws.com</c>.
/// Path-style requests are not supported. Directory bucket names must be unique in the
/// chosen Availability Zone. Bucket names must follow the format <c> <i>bucket_base_name</i>--<i>az-id</i>--x-s3</c>
/// (for example, <c> <i>DOC-EXAMPLE-BUCKET</i>--<i>usw2-az1</i>--x-s3</c>). For information
/// about bucket naming restrictions, see <a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-bucket-naming-rules.html">Directory
/// bucket naming rules</a> in the <i>Amazon S3 User Guide</i>.
/// </para>
///
/// <para>
/// <b>Access points</b> - When you use this action with an access point, you must provide
/// the alias of the access point in place of the bucket name or specify the access point
/// ARN. When using the access point ARN, you must direct requests to the access point
/// hostname. The access point hostname takes the form <i>AccessPointName</i>-<i>AccountId</i>.s3-accesspoint.<i>Region</i>.amazonaws.com.
/// When using this action with an access point through the Amazon Web Services SDKs,
/// you provide the access point ARN in place of the bucket name. For more information
/// about access point ARNs, see <a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-access-points.html">Using
/// access points</a> in the <i>Amazon S3 User Guide</i>.
/// </para>
///
/// <para>
/// <b>Object Lambda access points</b> - When you use this action with an Object Lambda
/// access point, you must direct requests to the Object Lambda access point hostname.
/// The Object Lambda access point hostname takes the form <i>AccessPointName</i>-<i>AccountId</i>.s3-object-lambda.<i>Region</i>.amazonaws.com.
/// </para>
/// <note>
/// <para>
/// Access points and Object Lambda access points are not supported by directory buckets.
/// </para>
/// </note>
/// <para>
/// <b>S3 on Outposts</b> - When you use this action with Amazon S3 on Outposts, you
/// must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes
/// the form <c> <i>AccessPointName</i>-<i>AccountId</i>.<i>outpostID</i>.s3-outposts.<i>Region</i>.amazonaws.com</c>.
/// When you use this action with S3 on Outposts through the Amazon Web Services SDKs,
/// you provide the Outposts access point ARN in place of the bucket name. For more information
/// about S3 on Outposts ARNs, see <a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/S3onOutposts.html">What
/// is S3 on Outposts?</a> in the <i>Amazon S3 User Guide</i>.
/// </para>
/// </summary>
[Parameter(Position = 0, Mandatory = true, ValueFromPipelineByPropertyName = true, ValueFromPipeline = true)]
[Amazon.PowerShell.Common.AWSRequiredParameter]
public System.String BucketName { get; set; }
#endregion
#endregion
#region File Download Parameters
#region Parameter Key
/// <summary>
/// The key that identifies the single object in S3.
/// </summary>
[Parameter(Position = 1, ParameterSetName = ParamSet_ToLocalFile, Mandatory = true, ValueFromPipelineByPropertyName = true)]
[Amazon.PowerShell.Common.AWSRequiredParameter]
public System.String Key { get; set; }
#endregion
#region Parameter File
/// <summary>
/// The full path to the local file that will be created.
/// </summary>
[Parameter(Position = 2, ParameterSetName = ParamSet_ToLocalFile, Mandatory = true, ValueFromPipelineByPropertyName = true)]
[Parameter(ParameterSetName = ParamSet_FromS3Object, ValueFromPipelineByPropertyName = true)]
[Amazon.PowerShell.Common.AWSRequiredParameter(ParameterSets = new[] { ParamSet_ToLocalFile })]
public System.String File { get; set; }
#endregion
#region Parameter Version
/// <summary>
/// If specified, the specific version of the S3 object is returned.
/// </summary>
[Alias("VersionId")]
[Parameter(Position = 3, ParameterSetName = ParamSet_ToLocalFile, ValueFromPipelineByPropertyName = true)]
public System.String Version { get; set; }
#endregion
#endregion
#region Folder Download Parameters
#region Parameter KeyPrefix
/// <summary>
/// <para>
/// The key prefix that identifies the set of S3 objects to be downloaded. The
/// key structure is preserved as the folder hierarchy under the destination folder.
/// </para>
/// <para>
/// To indicate that all content in the bucket is to be downloaded, values of
/// '/', '\', '*', '/*' or '\*' may be used for this parameter.
/// </summary>
[Alias("Prefix")]
[Parameter(Position = 1, ParameterSetName = ParamSet_ToLocalFolder, ValueFromPipelineByPropertyName = true)]
public System.String KeyPrefix { get; set; }
#endregion
#region Parameter Folder
/// <summary>
/// The full path to a local folder; all downloaded content will be placed under this folder,
/// with subfolders maintaining the S3 object key hierarchies.
/// </summary>
[Alias("Directory")]
[Parameter(Position = 2, ParameterSetName = ParamSet_ToLocalFolder, Mandatory = true, ValueFromPipelineByPropertyName = true)]
[Parameter(ParameterSetName = ParamSet_FromS3Object, ValueFromPipelineByPropertyName = true)]
[Amazon.PowerShell.Common.AWSRequiredParameter(ParameterSets = new[] { ParamSet_ToLocalFolder })]
public System.String Folder { get; set; }
#endregion
#region Parameter DisableSlashCorrection
/// <summary>
/// By default if KeyPrefix doesn't have a trailing '/' then a '/' is appended to mimic a virtual S3 directory. If the
/// KeyPrefix is not meant to be S3 virtual directory set DisableSlashCorrection to true to disable the behavior
/// for adding a trailing '/' to the KeyPrefix value.
/// </summary>
[Parameter(ParameterSetName = ParamSet_ToLocalFolder, ValueFromPipelineByPropertyName = true)]
public bool DisableSlashCorrection { get; set; }
#endregion
#endregion
#region S3Object Download Parameters
#region Parameter S3Object
/// <summary>
/// <para>
/// Amazon.S3.Model.S3Object instance containing the bucketname and key of the object to download.
/// If the supplied object is an Amazon.S3.Model.S3ObjectVersion instance (derived from S3Object),
/// the version of the object to download will be inferred automatically.
/// </para>
/// <para>
/// The object identified by the supplied S3Object can be downloaded to a specific file (by supplying
/// a value for the -File parameter) or to a folder (specified using the -Folder parameter). When
/// downloading to a folder, the object key is used as the filename. Note that object keys that are not
/// valid filenames for the host system could cause an exception to be thrown.
/// </para>
/// </summary>
[Parameter(ValueFromPipeline=true, ParameterSetName=ParamSet_FromS3Object, Mandatory=true, ValueFromPipelineByPropertyName = true)]
[Amazon.PowerShell.Common.AWSRequiredParameter]
public S3Object S3Object { get; set; }
#endregion
#endregion
#region Common Optional Parameters
#region Parameter ModifiedSinceDate
/// <summary>
/// If specified, only objects that have been modified since this date will be downloaded.
/// <para>This parameter is deprecated.</para>
/// </summary>
[Parameter(ValueFromPipelineByPropertyName = true)]
[System.ObsoleteAttribute("This parameter is deprecated because it doesn't honor DateTimeKind. Use UtcModifiedSinceDate instead")]
public System.DateTime ModifiedSinceDate { get; set; }
#endregion
#region Parameter UnmodifiedSinceDate
/// <summary>
/// If specified, only objects that have not been modified since this date will be downloaded.
/// <para>This parameter is deprecated.</para>
/// </summary>
[Parameter(ValueFromPipelineByPropertyName = true)]
[System.ObsoleteAttribute("This parameter is deprecated because it doesn't honor DateTimeKind. Use UtcUnmodifiedSinceDate instead")]
public System.DateTime UnmodifiedSinceDate { get; set; }
#endregion
#region Parameter UtcModifiedSinceDate
/// <summary>
/// If specified, only objects that have been modified since this date will be downloaded.
/// </summary>
[Parameter(ValueFromPipelineByPropertyName = true)]
public System.DateTime UtcModifiedSinceDate { get; set; }
#endregion
#region Parameter UtcUnmodifiedSinceDate
/// <summary>
/// If specified, only objects that have not been modified since this date will be downloaded.
/// </summary>
[Parameter(ValueFromPipelineByPropertyName = true)]
public System.DateTime UtcUnmodifiedSinceDate { get; set; }
#endregion
#region Parameter ServerSideEncryptionCustomerMethod
/// <summary>
/// Specifies the server-side encryption algorithm to be used with the customer provided key.
/// Allowable values: None or AES256.
/// </summary>
[Parameter(ParameterSetName = ParamSet_ToLocalFile, ValueFromPipelineByPropertyName = true)]
[Parameter(ParameterSetName = ParamSet_FromS3Object, ValueFromPipelineByPropertyName = true)]
[AWSConstantClassSource("Amazon.S3.ServerSideEncryptionCustomerMethod")]
public Amazon.S3.ServerSideEncryptionCustomerMethod ServerSideEncryptionCustomerMethod { get; set; }
#endregion
#region Parameter ServerSideEncryptionCustomerProvidedKey
/// <summary>
/// Specifies base64-encoded encryption key for Amazon S3 to use to decrypt the object.
/// </summary>
[Parameter(ParameterSetName = ParamSet_ToLocalFile, ValueFromPipelineByPropertyName = true)]
[Parameter(ParameterSetName = ParamSet_FromS3Object, ValueFromPipelineByPropertyName = true)]
public System.String ServerSideEncryptionCustomerProvidedKey { get; set; }
#endregion
#region Parameter ServerSideEncryptionCustomerProvidedKeyMD5
/// <summary>
/// Specifies base64-encoded MD5 of the encryption key for Amazon S3 to use to decrypt the object. This field is optional, the SDK will calculate the MD5 if this is not set.
/// </summary>
[Parameter(ParameterSetName = ParamSet_ToLocalFile, ValueFromPipelineByPropertyName = true)]
[Parameter(ParameterSetName = ParamSet_FromS3Object, ValueFromPipelineByPropertyName = true)]
public System.String ServerSideEncryptionCustomerProvidedKeyMD5 { get; set; }
#endregion
#region Parameter ChecksumMode
/// <summary>
/// This must be enabled to retrieve the checksum. In addition, if you enable <code>ChecksumMode</code>
/// and the object is KMS encrypted, you must have permission to the <code>kms:Decrypt</code> action
/// for the request to succeed.
/// </summary>
[Parameter(ParameterSetName = ParamSet_ToLocalFile, ValueFromPipelineByPropertyName = true)]
[Parameter(ParameterSetName = ParamSet_FromS3Object, ValueFromPipelineByPropertyName = true)]
[AWSConstantClassSource("Amazon.S3.ChecksumMode")]
public ChecksumMode ChecksumMode { get; set; }
#endregion
#endregion
protected override void ProcessRecord()
{
base.ProcessRecord();
var context = new CmdletContext
{
BucketName = this.BucketName
};
switch (this.ParameterSetName)
{
case ParamSet_ToLocalFile:
{
context.Key = AmazonS3Helper.CleanKey(this.Key);
base.UserAgentAddition = AmazonS3Helper.GetCleanKeyUserAgentAdditionString(this.Key, context.Key);
context.File = PSHelpers.PSPathToAbsolute(this.SessionState.Path, this.File);
context.Version = this.Version;
}
break;
case ParamSet_ToLocalFolder:
{
context.OriginalKeyPrefix = this.KeyPrefix;
context.KeyPrefix = rootIndicators.Contains<string>(this.KeyPrefix, StringComparer.OrdinalIgnoreCase)
? "/" : AmazonS3Helper.CleanKey(this.KeyPrefix);
base.UserAgentAddition = AmazonS3Helper.GetCleanKeyUserAgentAdditionString(this.KeyPrefix, context.KeyPrefix);
context.Folder = PSHelpers.PSPathToAbsolute(this.SessionState.Path, this.Folder);
context.DisableSlashCorrection = this.DisableSlashCorrection;
}
break;
case ParamSet_FromS3Object:
{
context.BucketName = this.S3Object.BucketName;
context.Key = this.S3Object.Key;
var s3ObjectVersion = this.S3Object as S3ObjectVersion;
context.Version = s3ObjectVersion == null ? null : s3ObjectVersion.VersionId;
if (this.ParameterWasBound("File"))
{
context.File = PSHelpers.PSPathToAbsolute(this.SessionState.Path, this.File);
}
else
{
var path = PSHelpers.PSPathToAbsolute(this.SessionState.Path, this.Folder);
context.File = Path.Combine(path, S3Object.Key);
}
}
break;
}
if (ParameterWasBound("UtcModifiedSinceDate"))
context.UtcModifiedSinceDate = this.UtcModifiedSinceDate;
if (ParameterWasBound("UtcUnmodifiedSinceDate"))
context.UtcUnmodifiedSinceDate = this.UtcUnmodifiedSinceDate;
#pragma warning disable CS0618, CS0612 //A class member was marked with the Obsolete attribute
if (ParameterWasBound("ModifiedSinceDate"))
context.ModifiedSinceDate = this.ModifiedSinceDate;
if (ParameterWasBound("UnmodifiedSinceDate"))
context.UnmodifiedSinceDate = this.UnmodifiedSinceDate;
#pragma warning restore CS0618, CS0612 //A class member was marked with the Obsolete attribute
if (ParameterWasBound("ServerSideEncryptionCustomerMethod"))
context.ServerSideEncryptionCustomerMethod = this.ServerSideEncryptionCustomerMethod;
context.ServerSideEncryptionCustomerProvidedKey = this.ServerSideEncryptionCustomerProvidedKey;
context.ServerSideEncryptionCustomerProvidedKeyMD5 = this.ServerSideEncryptionCustomerProvidedKeyMD5;
if (ParameterWasBound("ChecksumMode"))
context.ChecksumMode = this.ChecksumMode;
var output = Execute(context) as CmdletOutput;
ProcessOutput(output);
}
#region IExecutor Members
public object Execute(ExecutorContext context)
{
var cmdletContext = context as CmdletContext;
if (!string.IsNullOrEmpty(cmdletContext.File))
return DownloadFileFromS3(cmdletContext);
else
return DownloadFolderFromS3(cmdletContext);
}
CmdletOutput DownloadFileFromS3(ExecutorContext context)
{
var cmdletContext = context as CmdletContext;
var request = new TransferUtilityDownloadRequest
{
BucketName = cmdletContext.BucketName,
FilePath = cmdletContext.File,
Key = cmdletContext.Key
};
if (!string.IsNullOrEmpty(cmdletContext.Version))
request.VersionId = cmdletContext.Version;
if (cmdletContext.UtcModifiedSinceDate.HasValue)
request.ModifiedSinceDateUtc = cmdletContext.UtcModifiedSinceDate.Value;
if (cmdletContext.UtcUnmodifiedSinceDate.HasValue)
request.UnmodifiedSinceDateUtc = cmdletContext.UtcUnmodifiedSinceDate.Value;
#pragma warning disable CS0618, CS0612 //A class member was marked with the Obsolete attribute
if (cmdletContext.ModifiedSinceDate.HasValue)
{
if (cmdletContext.UtcModifiedSinceDate != null)
{
throw new ArgumentException("Parameters ModifiedSinceDate and UtcModifiedSinceDate are mutually exclusive.");
}
request.ModifiedSinceDate = cmdletContext.ModifiedSinceDate.Value;
}
if (cmdletContext.UnmodifiedSinceDate.HasValue)
{
if (cmdletContext.UtcUnmodifiedSinceDate != null)
{
throw new ArgumentException("Parameters UnmodifiedSinceDate and UtcUnmodifiedSinceDate are mutually exclusive.");
}
request.UnmodifiedSinceDate = cmdletContext.UnmodifiedSinceDate.Value;
}
#pragma warning restore CS0618, CS0612 //A class member was marked with the Obsolete attribute
request.ServerSideEncryptionCustomerMethod = cmdletContext.ServerSideEncryptionCustomerMethod;
request.ServerSideEncryptionCustomerProvidedKey = cmdletContext.ServerSideEncryptionCustomerProvidedKey;
request.ServerSideEncryptionCustomerProvidedKeyMD5 = cmdletContext.ServerSideEncryptionCustomerProvidedKeyMD5;
request.ChecksumMode = cmdletContext.ChecksumMode;
CmdletOutput output;
using (var tu = new TransferUtility(Client ?? CreateClient(_CurrentCredentials, _RegionEndpoint)))
{
Utils.Common.WriteVerboseEndpointMessage(this, Client.Config, "Amazon S3 object download APIs");
var runner = new ProgressRunner(this);
var tracker = new DownloadFileProgressTracker(runner, handler => request.WriteObjectProgressEvent += handler, cmdletContext.Key);
output = runner.SafeRun(() => tu.Download(request), tracker);
if (output.ErrorResponse == null)
output.PipelineOutput = new FileInfo(cmdletContext.File);
}
return output;
}
CmdletOutput DownloadFolderFromS3(ExecutorContext context)
{
var cmdletContext = context as CmdletContext;
var request = new TransferUtilityDownloadDirectoryRequest
{
BucketName = cmdletContext.BucketName,
LocalDirectory = cmdletContext.Folder,
S3Directory = cmdletContext.KeyPrefix,
DisableSlashCorrection = cmdletContext.DisableSlashCorrection
};
if (cmdletContext.UtcModifiedSinceDate.HasValue)
request.ModifiedSinceDateUtc = cmdletContext.UtcModifiedSinceDate.Value;
if (cmdletContext.UtcUnmodifiedSinceDate.HasValue)
request.UnmodifiedSinceDateUtc = cmdletContext.UtcUnmodifiedSinceDate.Value;
#pragma warning disable CS0618, CS0612 //A class member was marked with the Obsolete attribute
if (cmdletContext.ModifiedSinceDate.HasValue)
{
if (cmdletContext.UtcModifiedSinceDate != null)
{
throw new ArgumentException("Parameters ModifiedSinceDate and UtcModifiedSinceDate are mutually exclusive.");
}
request.ModifiedSinceDate = cmdletContext.ModifiedSinceDate.Value;
}
if (cmdletContext.UnmodifiedSinceDate.HasValue)
{
if (cmdletContext.UtcUnmodifiedSinceDate != null)
{
throw new ArgumentException("Parameters UnmodifiedSinceDate and UtcUnmodifiedSinceDate are mutually exclusive.");
}
request.UnmodifiedSinceDate = cmdletContext.UnmodifiedSinceDate.Value;
}
#pragma warning restore CS0618, CS0612 //A class member was marked with the Obsolete attribute
CmdletOutput output;
using (var tu = new TransferUtility(Client ?? CreateClient(_CurrentCredentials, _RegionEndpoint)))
{
Utils.Common.WriteVerboseEndpointMessage(this, Client.Config, "Amazon S3 object download APIs");
var runner = new ProgressRunner(this);
var tracker = new DownloadFolderProgressTracker(runner, handler => request.DownloadedDirectoryProgressEvent += handler);
output = runner.SafeRun(() => tu.DownloadDirectory(request), tracker);
if (output.ErrorResponse == null)
output.PipelineOutput = new DirectoryInfo(cmdletContext.Folder);
WriteVerbose(string.Format("Downloaded {0} object(s) from bucket '{1}' with keyprefix '{2}' to '{3}'",
tracker.DownloadedCount,
cmdletContext.BucketName,
cmdletContext.OriginalKeyPrefix,
cmdletContext.Folder));
}
return output;
}
public ExecutorContext CreateContext()
{
return new CmdletContext();
}
#endregion
internal class CmdletContext : ExecutorContext
{
public String BucketName { get; set; }
public String Key { get; set; }
public String File { get; set; }
public string Version { get; set; }
public String OriginalKeyPrefix { get; set; }
public String KeyPrefix { get; set; }
public String Folder { get; set; }
[System.ObsoleteAttribute]
public DateTime? ModifiedSinceDate { get; set; }
[System.ObsoleteAttribute]
public DateTime? UnmodifiedSinceDate { get; set; }
public DateTime? UtcModifiedSinceDate { get; set; }
public DateTime? UtcUnmodifiedSinceDate { get; set; }
public ServerSideEncryptionCustomerMethod ServerSideEncryptionCustomerMethod { get; set; }
public string ServerSideEncryptionCustomerProvidedKey { get; set; }
public string ServerSideEncryptionCustomerProvidedKeyMD5 { get; set; }
public ChecksumMode ChecksumMode { get; set; }
public bool DisableSlashCorrection { get; set; }
}
internal class DownloadFileProgressTracker : ProgressTracker<WriteObjectProgressArgs>
{
int _currentPercent = 0;
readonly string _key;
const string DownloadingFileActivity = "Downloading";
const string ProgressMsgFormat = "File {0}...{1}%";
public override string Activity
{
get { return DownloadingFileActivity; }
}
public DownloadFileProgressTracker(ProgressRunner runner, Action<EventHandler<WriteObjectProgressArgs>> subscribe, string key)
: base(runner, subscribe)
{
this._key = key;
ReportProgress(0, ProgressMsgFormat, _key, 0);
}
public override void ReportProgress(WriteObjectProgressArgs args)
{
if (args.PercentDone != _currentPercent)
{
_currentPercent = args.PercentDone;
ReportProgress(args.PercentDone, ProgressMsgFormat, _key, args.PercentDone);
}
}
}
internal class DownloadFolderProgressTracker : ProgressTracker<DownloadDirectoryProgressArgs>
{
int _fileDownloadCount = 0;
string _currentFile = string.Empty;
const string DownloadingFolderActivity = "Downloading";
public override string Activity
{
get { return DownloadingFolderActivity; }
}
public DownloadFolderProgressTracker(ProgressRunner runner, Action<EventHandler<DownloadDirectoryProgressArgs>> subscribe)
: base(runner, subscribe)
{
ReportProgress(0, "Downloading files...");
}
public int DownloadedCount { get { return _fileDownloadCount; } }
public override void ReportProgress(DownloadDirectoryProgressArgs args)
{
if (string.Compare(_currentFile, args.CurrentFile, StringComparison.CurrentCultureIgnoreCase) != 0)
{
_currentFile = args.CurrentFile;
_fileDownloadCount = args.NumberOfFilesDownloaded;
ReportProgress(args.NumberOfFilesDownloaded, args.TotalNumberOfFiles, "Downloaded {0} files, current file {1}", args.NumberOfFilesDownloaded, args.CurrentFile);
}
}
}
}
}