/// <summary>The core logic for uploading a stream. It is used by the upload and resume methods.</summary> private async Task <IUploadProgress> UploadCoreAsync(CancellationToken cancellationToken) { try { using (var callback = new ServerErrorCallback(this)) { while (!await SendNextChunkAsync(ContentStream, cancellationToken).ConfigureAwait(false)) { UpdateProgress(new ResumableUploadProgress(UploadStatus.Uploading, BytesServerReceived)); } UpdateProgress(new ResumableUploadProgress(UploadStatus.Completed, BytesServerReceived)); } } catch (TaskCanceledException ex) { Logger.Error(ex, "MediaUpload[{0}] - Task was canceled", UploadUri); UpdateProgress(new ResumableUploadProgress(ex, BytesServerReceived)); throw ex; } catch (Exception ex) { Logger.Error(ex, "MediaUpload[{0}] - Exception occurred while uploading media", UploadUri); UpdateProgress(new ResumableUploadProgress(ex, BytesServerReceived)); } return(Progress); }
/// <summary> /// Uploads the content to the server using the given cancellation token. This method is used for both async /// and sync operation. /// </summary> private async Task<IUploadProgress> Upload(CancellationToken cancellationToken) { try { BytesSent = 0; UpdateProgress(new ResumableUploadProgress(UploadStatus.Starting, 0)); // check if the stream length is known StreamLength = ContentStream.CanSeek ? ContentStream.Length : UnknownSize; UploadUri = await InitializeUpload(cancellationToken).ConfigureAwait(false); logger.Debug("MediaUpload[{0}] - Start uploading...", UploadUri); using (var callback = new ServerErrorCallback(this)) { while (!await SendNextChunk(ContentStream, cancellationToken).ConfigureAwait(false)) { UpdateProgress(new ResumableUploadProgress(UploadStatus.Uploading, BytesSent)); } UpdateProgress(new ResumableUploadProgress(UploadStatus.Completed, BytesSent)); } } catch (Exception ex) { logger.Error(ex, "MediaUpload[{0}] - Exception occurred while uploading media", UploadUri); UpdateProgress(new ResumableUploadProgress(ex, BytesSent)); } return Progress; }
/// <summary>Asynchronously resumes the upload form the last point it was interrupted.</summary> /// <param name="cancellationToken">A cancellation token to cancel operation.</param> public async Task <IUploadProgress> ResumeAsync(CancellationToken cancellationToken) { if (UploadUri == null) { Logger.Info("There isn't any upload in progress, so starting to upload again"); return(await UploadAsync(cancellationToken).ConfigureAwait(false)); } // The first "resuming" request is to query the server in which point the upload was interrupted. var range = String.Format("bytes */{0}", StreamLength < 0 ? "*" : StreamLength.ToString()); HttpRequestMessage request = new RequestBuilder() { BaseUri = UploadUri, Method = HttpConsts.Put }.CreateRequest(); request.SetEmptyContent().Headers.Add("Content-Range", range); try { HttpResponseMessage response; using (var callback = new ServerErrorCallback(this)) { response = await Service.HttpClient.SendAsync(request, cancellationToken) .ConfigureAwait(false); } if (await HandleResponse(response).ConfigureAwait(false)) { // All the media was successfully upload. UpdateProgress(new ResumableUploadProgress(UploadStatus.Completed, BytesServerReceived)); return(Progress); } } catch (TaskCanceledException ex) { Logger.Error(ex, "MediaUpload[{0}] - Task was canceled", UploadUri); UpdateProgress(new ResumableUploadProgress(ex, BytesServerReceived)); throw ex; } catch (Exception ex) { Logger.Error(ex, "MediaUpload[{0}] - Exception occurred while resuming uploading media", UploadUri); UpdateProgress(new ResumableUploadProgress(ex, BytesServerReceived)); return(Progress); } // Continue to upload the media stream. return(await UploadCoreAsync(cancellationToken).ConfigureAwait(false)); }
/// <summary> /// Asynchronously resumes the upload from the last point it was interrupted. /// Use when the program was restarted and you wish to resume the upload that was in progress when the program was halted. /// Implemented only for ContentStreams where .CanSeek is True. /// </summary> /// <remarks> /// In your application's UploadSessionData Event Handler, store UploadUri.AbsoluteUri property value (resumable session URI string value) /// to persistent storage for use with Resume() or ResumeAsync() upon a program restart. /// It is strongly recommended that the FullPathFilename of the media file that is being uploaded is saved also so that a subsequent execution of the /// program can compare the saved FullPathFilename value to the FullPathFilename of the media file that it has opened for uploading. /// You do not need to seek to restart point in the ContentStream file. /// </remarks> /// <param name="uploadUri">VideosResource.InsertMediaUpload UploadUri property value that was saved to persistent storage during a prior execution.</param> /// <param name="cancellationToken">A cancellation token to cancel the asynchronous operation.</param> public async Task <IUploadProgress> ResumeAsync(Uri uploadUri, CancellationToken cancellationToken) { // When called with uploadUri parameter of non-null value, the UploadUri is being // provided upon a program restart to resume a previously interrupted upload. if (uploadUri != null) { if (ContentStream.CanSeek) { Logger.Info("Resuming after program restart: UploadUri={0}", uploadUri); UploadUri = uploadUri; StreamLength = ContentStream.Length; } else { throw new NotImplementedException("Resume after program restart not allowed when ContentStream.CanSeek is false"); } } if (UploadUri == null) { Logger.Info("There isn't any upload in progress, so starting to upload again"); return(await UploadAsync(cancellationToken).ConfigureAwait(false)); } // The first "resuming" request is to query the server in which point the upload was interrupted. var range = String.Format("bytes */{0}", StreamLength < 0 ? "*" : StreamLength.ToString()); HttpRequestMessage request = new RequestBuilder() { BaseUri = UploadUri, Method = HttpConsts.Put }.CreateRequest(); request.SetEmptyContent().Headers.Add("Content-Range", range); try { HttpResponseMessage response; using (var callback = new ServerErrorCallback(this)) { response = await HttpClient.SendAsync(request, cancellationToken) .ConfigureAwait(false); } if (await HandleResponse(response).ConfigureAwait(false)) { // All the media was successfully upload. UpdateProgress(new ResumableUploadProgress(UploadStatus.Completed, BytesServerReceived)); return(Progress); } } catch (TaskCanceledException ex) { Logger.Error(ex, "MediaUpload[{0}] - Task was canceled", UploadUri); UpdateProgress(new ResumableUploadProgress(ex, BytesServerReceived)); throw ex; } catch (Exception ex) { Logger.Error(ex, "MediaUpload[{0}] - Exception occurred while resuming uploading media", UploadUri); UpdateProgress(new ResumableUploadProgress(ex, BytesServerReceived)); return(Progress); } // Continue to upload the media stream. return(await UploadCoreAsync(cancellationToken).ConfigureAwait(false)); }