Ejemplo n.º 1
0
        /// <summary>Creates a request to initialize a request.</summary>
        private HttpRequestMessage CreateInitializeRequest()
        {
            var builder = new RequestBuilder()
            {
                BaseUri = new Uri(Service.BaseUri),
                Path    = Path,
                Method  = HttpMethod,
            };

            // init parameters
            builder.AddParameter(RequestParameterType.Query, "key", Service.ApiKey);
            builder.AddParameter(RequestParameterType.Query, "uploadType", "resumable");
            SetAllPropertyValues(builder);

            HttpRequestMessage request = builder.CreateRequest();

            if (ContentType != null)
            {
                request.Headers.Add(PayloadContentTypeHeader, ContentType);
            }

            // if the length is unknown at the time of this request, omit "X-Upload-Content-Length" header
            if (StreamLength != UnknownSize)
            {
                request.Headers.Add(PayloadContentLengthHeader, StreamLength.ToString());
            }

            Service.SetRequestSerailizedContent(request, Body);
            return(request);
        }
Ejemplo n.º 2
0
        /// <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>
        /// Build a content range header of the form: "bytes X-Y/T" where:
        /// <list type="">
        /// <item>X is the first byte being sent.</item>
        /// <item>Y is the last byte in the range being sent (inclusive).</item>
        /// <item>T is the total number of bytes in the range or * for unknown size.</item>
        /// </list>
        /// </summary>
        /// <remarks>
        /// See: RFC2616 HTTP/1.1, Section 14.16 Header Field Definitions, Content-Range
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16
        /// </remarks>
        /// <param name="chunkStart">Start of the chunk.</param>
        /// <param name="chunkSize">Size of the chunk being sent.</param>
        /// <returns>The content range header value.</returns>
        private string GetContentRangeHeader(long chunkStart, long chunkSize)
        {
            string strLength = StreamLength < 0 ? "*" : StreamLength.ToString();

            // If a file of length 0 is sent, one chunk needs to be sent with 0 size.
            // This chunk cannot be specified with the standard (inclusive) range header.
            // In this case, use * to indicate no bytes sent in the Content-Range header.
            if (chunkStart == 0 && chunkSize == 0 && StreamLength == 0)
            {
                return(ZeroByteContentRangeHeader);
            }
            else
            {
                long chunkEnd = chunkStart + chunkSize - 1;
                return(String.Format("bytes {0}-{1}/{2}", chunkStart, chunkEnd, strLength));
            }
        }
            protected override Task <HttpResponseMessage> SendAsyncCore(HttpRequestMessage request,
                                                                        CancellationToken cancellationToken)
            {
                var response = new HttpResponseMessage();
                var range    = string.Empty;

                switch (Calls)
                {
                case 1:
                    if (PathParameters == null)
                    {
                        Assert.That(request.RequestUri.AbsolutePath, Is.EqualTo("/"));
                    }
                    else
                    {
                        Assert.That(request.RequestUri.AbsolutePath, Is.EqualTo("/" + PathParameters));
                    }
                    Assert.That(request.RequestUri.Query, Is.EqualTo("?uploadType=resumable" + QueryParameters));

                    Assert.That(request.Headers.GetValues("X-Upload-Content-Type").First(),
                                Is.EqualTo("text/plain"));
                    Assert.That(request.Headers.GetValues("X-Upload-Content-Length").First(),
                                Is.EqualTo(StreamLength.ToString()));

                    response.Headers.Location = uploadUri;
                    break;

                case 2:
                    Assert.That(request.RequestUri, Is.EqualTo(uploadUri));
                    range = String.Format("bytes 0-{0}/{1}", StreamLength - 1, StreamLength);
                    Assert.That(request.Content.Headers.GetValues("Content-Range").First(), Is.EqualTo(range));
                    Assert.That(request.Content.Headers.ContentLength, Is.EqualTo(StreamLength));
                    break;
                }

                TaskCompletionSource <HttpResponseMessage> tcs = new TaskCompletionSource <HttpResponseMessage>();

                tcs.SetResult(response);
                return(tcs.Task);
            }
Ejemplo n.º 5
0
        /// <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));
        }