Index: Src/GoogleApis/Apis/[Media]/Download/MediaDownloader.cs =================================================================== --- a/Src/GoogleApis/Apis/[Media]/Download/MediaDownloader.cs +++ b/Src/GoogleApis/Apis/[Media]/Download/MediaDownloader.cs @@ -20,6 +20,7 @@ using System.Threading; using System.Threading.Tasks; +using Google.Apis.Logging; using Google.Apis.Requests; using Google.Apis.Services; using Google.Apis.Util; @@ -32,6 +33,8 @@ /// public class MediaDownloader : IMediaDownloader { + private static readonly ILogger Logger = ApplicationContext.Logger.ForType(); + /// The service which this downloader belongs to. private readonly IClientService service; @@ -124,7 +127,7 @@ public IDownloadProgress Download(string url, Stream stream) { - return DownloadCore(url, stream, CancellationToken.None).Result; + return DownloadCoreAsync(url, stream, CancellationToken.None).Result; } public async Task DownloadAsync(string url, Stream stream) @@ -135,40 +138,13 @@ public async Task DownloadAsync(string url, Stream stream, CancellationToken cancellationToken) { - return await DownloadAsyncCore(url, stream, cancellationToken); + return await DownloadCoreAsync(url, stream, cancellationToken).ConfigureAwait(false); } #endregion #endregion - private Task DownloadAsyncCore(string url, Stream stream, - CancellationToken cancellationToken) - { - TaskCompletionSource tcs = new TaskCompletionSource(); - Task.Factory.StartNew(async () => - { - try - { - var progress = await DownloadCore(url, stream, cancellationToken).ConfigureAwait(false); - if (progress.Exception != null) - { - tcs.SetException(progress.Exception); - } - else - { - tcs.SetResult(progress); - } - } - catch (Exception ex) - { - // exception was thrown - it must be set on the task completion source - tcs.SetException(ex); - } - }).ConfigureAwait(false); - return tcs.Task; - } - /// /// The core download logic. It downloads the media in parts, where each part's size is defined by /// (in bytes). @@ -178,10 +154,9 @@ /// A cancellation token to cancel this download in the middle. /// A task with the download progress object. If an exception occurred during the download, its /// property will contain the exception. - private async Task DownloadCore(string url, Stream stream, + private async Task DownloadCoreAsync(string url, Stream stream, CancellationToken cancellationToken) { - // validate the parameters url.ThrowIfNull("url"); stream.ThrowIfNull("stream"); if (!stream.CanWrite) @@ -196,16 +171,14 @@ try { - // this "infinite" loop stops when the "to" byte position in the "Content-Range" header is the last + // This "infinite" loop stops when the "to" byte position in the "Content-Range" header is the last // byte of the media ("length"-1 in the "Content-Range" header). // e.g. "Content-Range: 200-299/300" - "to"(299) = "length"(300) - 1. while (true) { - cancellationToken.ThrowIfCancellationRequested(); - var currentRequestLastBytePos = currentRequestFirstBytePos + ChunkSize - 1; - // create the request and set the Range header + // Create the request and set the Range header. var request = builder.CreateRequest(); request.Headers.Range = new RangeHeaderValue(currentRequestFirstBytePos, currentRequestLastBytePos); @@ -213,11 +186,11 @@ using (var response = await service.HttpClient.SendAsync(request, cancellationToken). ConfigureAwait(false)) { - // read the content and copy to the parameter's stream + // Read the content and copy to the parameter's stream. var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); responseStream.CopyTo(stream); - // read the headers and check if all the media content was already downloaded + // Read the headers and check if all the media content was already downloaded. var contentRange = response.Content.Headers.ContentRange; currentRequestFirstBytePos = contentRange.To.Value + 1; long mediaContentLength = contentRange.Length.Value; @@ -233,8 +206,15 @@ UpdateProgress(new DownloadProgress(DownloadStatus.Downloading, currentRequestFirstBytePos)); } } + catch (TaskCanceledException ex) + { + Logger.Error(ex, "Download media was canceled"); + UpdateProgress(new DownloadProgress(ex, currentRequestFirstBytePos)); + throw ex; + } catch (Exception ex) { + Logger.Error(ex, "Exception occurred while downloading media"); var progress = new DownloadProgress(ex, currentRequestFirstBytePos); UpdateProgress(progress); return progress;