Exemple #1
0
        private void WriteMultipleContent(Stream stream, IHttpContent content, Action <UploadStatusMessage> uploadStatusCallback, int blockSize)
        {
            long             contentLength        = content.GetContentLength();
            long             totalContentUploaded = 0;
            MultipartContent multipartContent     = content as MultipartContent;

            foreach (IHttpContent singleContent in multipartContent)
            {
                stream.Write(multipartContent.BoundaryStartBytes, 0, multipartContent.BoundaryStartBytes.Length);
                totalContentUploaded += multipartContent.BoundaryStartBytes.Length;

                foreach (var header in singleContent.Headers)
                {
                    byte[] headerBytes = Encoding.UTF8.GetBytes(header.Key + ": " + header.Value);

                    stream.Write(headerBytes, 0, headerBytes.Length);
                    totalContentUploaded += headerBytes.Length;

                    stream.Write(multipartContent.CRLFBytes, 0, multipartContent.CRLFBytes.Length);
                    totalContentUploaded += multipartContent.CRLFBytes.Length;
                }

                stream.Write(multipartContent.CRLFBytes, 0, multipartContent.CRLFBytes.Length);
                totalContentUploaded += multipartContent.CRLFBytes.Length;

                totalContentUploaded += WriteSingleContent(stream, singleContent, uploadStatusCallback, blockSize, contentLength, totalContentUploaded);

                stream.Write(multipartContent.CRLFBytes, 0, multipartContent.CRLFBytes.Length);
                totalContentUploaded += multipartContent.CRLFBytes.Length;
            }

            if (!multipartContent.Any())
            {
                stream.Write(multipartContent.BoundaryStartBytes, 0, multipartContent.BoundaryStartBytes.Length);
                totalContentUploaded += multipartContent.BoundaryStartBytes.Length;
            }

            stream.Write(multipartContent.BoundaryEndBytes, 0, multipartContent.BoundaryEndBytes.Length);
            totalContentUploaded += multipartContent.BoundaryEndBytes.Length;

            RaiseUploadStatusCallback(uploadStatusCallback, contentLength, (multipartContent.CRLFBytes.Length * 2) + multipartContent.BoundaryEndBytes.Length, totalContentUploaded);
        }
			/// <summary>
			/// <see cref="HttpContent"/> implementation which provides a byte range view over a stream used to generate HTTP
			/// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend 
			/// of the selected resource represented by the <paramref name="content"/> parameter then an 
			/// <see cref="InvalidByteRangeException"/> is thrown indicating the valid Content-Range of the content. 
			/// </summary>
			/// <param name="content">The stream over which to generate a byte range view.</param>
			/// <param name="range">The range or ranges, typically obtained from the Range HTTP request header field.</param>
			/// <param name="mediaType">The media type of the content stream.</param>
			/// <param name="bufferSize">The buffer size used when copying the content stream.</param>
			public ByteRangeStreamContent(Stream content, RangeHeaderValue range, MediaTypeHeaderValue mediaType, int bufferSize)
			{

				try
				{
					// If we have more than one range then we use a multipart/byteranges content type as wrapper.
					// Otherwise we use a non-multipart response.
					if (range.Ranges.Count > 1)
					{
						// Create Multipart content and copy headers to this content
						MultipartContent rangeContent = new MultipartContent(ByteRangesContentSubtype);
						_byteRangeContent = rangeContent;

						foreach (RangeItemHeaderValue rangeValue in range.Ranges)
						{
							try
							{
								ByteRangeStream rangeStream = new ByteRangeStream(content, rangeValue);
								HttpContent rangeBodyPart = new StreamContent(rangeStream, bufferSize);
								rangeBodyPart.Headers.ContentType = mediaType;
								rangeBodyPart.Headers.ContentRange = rangeStream.ContentRange;
								rangeContent.Add(rangeBodyPart);
							}
							catch (ArgumentOutOfRangeException)
							{
								// We ignore range errors until we check that we have at least one valid range
							}
						}

						// If no overlapping ranges were found then stop
						if (!rangeContent.Any())
						{
							ContentRangeHeaderValue actualContentRange = new ContentRangeHeaderValue(content.Length);
							string msg = "ByteRangeStreamNoneOverlap";
							throw new InvalidByteRangeException(actualContentRange, msg);
						}
					}
					else if (range.Ranges.Count == 1)
					{
						try
						{
							ByteRangeStream rangeStream = new ByteRangeStream(content, range.Ranges.First());
							_byteRangeContent = new StreamContent(rangeStream, bufferSize);
							_byteRangeContent.Headers.ContentType = mediaType;
							_byteRangeContent.Headers.ContentRange = rangeStream.ContentRange;
						}
						catch (ArgumentOutOfRangeException)
						{
							ContentRangeHeaderValue actualContentRange = new ContentRangeHeaderValue(content.Length);
							string msg = "ByteRangeStreamNoOverlap";
							throw new InvalidByteRangeException(actualContentRange, msg);
						}
					}
					else
					{
						throw new ArgumentException("range");
					}

					// Copy headers from byte range content so that we get the right content type etc.
					_byteRangeContent.Headers.CopyTo(Headers);

					_content = content;
					_start = content.Position;
				}
				catch
				{
					if (_byteRangeContent != null)
					{
						_byteRangeContent.Dispose();
					}
					throw;
				}
			}
        /// <summary>
        /// <see cref="HttpContent"/> implementation which provides a byte range view over a stream used to generate HTTP
        /// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend 
        /// of the selected resource represented by the <paramref name="content"/> parameter then an 
        /// <see cref="InvalidByteRangeException"/> is thrown indicating the valid Content-Range of the content. 
        /// </summary>
        /// <param name="content">The stream over which to generate a byte range view.</param>
        /// <param name="range">The range or ranges, typically obtained from the Range HTTP request header field.</param>
        /// <param name="mediaType">The media type of the content stream.</param>
        /// <param name="bufferSize">The buffer size used when copying the content stream.</param>
        public ByteRangeStreamContent(Stream content, RangeHeaderValue range, MediaTypeHeaderValue mediaType, int bufferSize)
        {
            if (content == null)
            {
                throw new ArgumentNullException("content");
            }
            if (!content.CanSeek)
            {
                throw new ArgumentException("content", RS.Format(Resources.ByteRangeStreamNotSeekable, typeof(ByteRangeStreamContent).Name));
            }
            if (range == null)
            {
                throw new ArgumentNullException("range");
            }
            if (mediaType == null)
            {
                throw new ArgumentNullException("mediaType");
            }
            if (bufferSize < MinBufferSize)
            {
                throw new ArgumentOutOfRangeException("bufferSize", bufferSize, RS.Format(Resources.ArgumentMustBeGreaterThanOrEqualTo, MinBufferSize));
            }
            if (!range.Unit.Equals(SupportedRangeUnit, StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentException(RS.Format(Resources.ByteRangeStreamContentNotBytesRange, range.Unit, SupportedRangeUnit), "range");
            }

            try
            {
                // If we have more than one range then we use a multipart/byteranges content type as wrapper.
                // Otherwise we use a non-multipart response.
                if (range.Ranges.Count > 1)
                {
                    // Create Multipart content and copy headers to this content
                    MultipartContent rangeContent = new MultipartContent(ByteRangesContentSubtype);
                    _byteRangeContent = rangeContent;

                    foreach (RangeItemHeaderValue rangeValue in range.Ranges)
                    {
                        try
                        {
                            ByteRangeStream rangeStream = new ByteRangeStream(content, rangeValue);
                            HttpContent rangeBodyPart = new StreamContent(rangeStream, bufferSize);
                            rangeBodyPart.Headers.ContentType = mediaType;
                            rangeBodyPart.Headers.ContentRange = rangeStream.ContentRange;
                            rangeContent.Add(rangeBodyPart);
                        }
                        catch (ArgumentOutOfRangeException)
                        {
                            // We ignore range errors until we check that we have at least one valid range
                        }
                    }

                    // If no overlapping ranges were found then stop
                    if (!rangeContent.Any())
                    {
                        ContentRangeHeaderValue actualContentRange = new ContentRangeHeaderValue(content.Length);
                        string msg = RS.Format(Resources.ByteRangeStreamNoneOverlap, range.ToString());
                        throw new InvalidByteRangeException(actualContentRange, msg);
                    }
                }
                else if (range.Ranges.Count == 1)
                {
                    try
                    {
                        ByteRangeStream rangeStream = new ByteRangeStream(content, range.Ranges.First());
                        _byteRangeContent = new StreamContent(rangeStream, bufferSize);
                        _byteRangeContent.Headers.ContentType = mediaType;
                        _byteRangeContent.Headers.ContentRange = rangeStream.ContentRange;
                    }
                    catch (ArgumentOutOfRangeException)
                    {
                        ContentRangeHeaderValue actualContentRange = new ContentRangeHeaderValue(content.Length);
                        string msg = RS.Format(Resources.ByteRangeStreamNoOverlap, range.ToString());
                        throw new InvalidByteRangeException(actualContentRange, msg);
                    }
                }
                else
                {
                    throw new ArgumentException(Resources.ByteRangeStreamContentNoRanges, "range");
                }

                // Copy headers from byte range content so that we get the right content type etc.
                foreach (KeyValuePair<string, IEnumerable<string>> header in _byteRangeContent.Headers)
                {
                    Headers.TryAddWithoutValidation(header.Key, header.Value);
                }

                _content = content;
                _start = content.Position;
            }
            catch
            {
                if (_byteRangeContent != null)
                {
                    _byteRangeContent.Dispose();
                }
                throw;
            }
        }
Exemple #4
0
        /// <summary>
        /// <see cref="HttpContent"/> implementation which provides a byte range view over a stream used to generate HTTP
        /// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend
        /// of the selected resource represented by the <paramref name="content"/> parameter then an
        /// <see cref="InvalidByteRangeException"/> is thrown indicating the valid Content-Range of the content.
        /// </summary>
        /// <param name="content">The stream over which to generate a byte range view.</param>
        /// <param name="range">The range or ranges, typically obtained from the Range HTTP request header field.</param>
        /// <param name="mediaType">The media type of the content stream.</param>
        /// <param name="bufferSize">The buffer size used when copying the content stream.</param>
        public ByteRangeStreamContent(Stream content, RangeHeaderValue range, MediaTypeHeaderValue mediaType, int bufferSize)
        {
            if (content == null)
            {
                throw Error.ArgumentNull("content");
            }
            if (!content.CanSeek)
            {
                throw Error.Argument("content", Resources.ByteRangeStreamNotSeekable, typeof(ByteRangeStreamContent).Name);
            }
            if (range == null)
            {
                throw Error.ArgumentNull("range");
            }
            if (mediaType == null)
            {
                throw Error.ArgumentNull("mediaType");
            }
            if (bufferSize < MinBufferSize)
            {
                throw Error.ArgumentMustBeGreaterThanOrEqualTo("bufferSize", bufferSize, MinBufferSize);
            }
            if (!range.Unit.Equals(SupportedRangeUnit, StringComparison.OrdinalIgnoreCase))
            {
                throw Error.Argument("range", Resources.ByteRangeStreamContentNotBytesRange, range.Unit, SupportedRangeUnit);
            }

            try
            {
                // If we have more than one range then we use a multipart/byteranges content type as wrapper.
                // Otherwise we use a non-multipart response.
                if (range.Ranges.Count > 1)
                {
                    // Create Multipart content and copy headers to this content
                    MultipartContent rangeContent = new MultipartContent(ByteRangesContentSubtype);
                    this._byteRangeContent = rangeContent;

                    foreach (RangeItemHeaderValue rangeValue in range.Ranges)
                    {
                        try
                        {
                            ByteRangeStream rangeStream   = new ByteRangeStream(content, rangeValue);
                            HttpContent     rangeBodyPart = new StreamContent(rangeStream, bufferSize);
                            rangeBodyPart.Headers.ContentType  = mediaType;
                            rangeBodyPart.Headers.ContentRange = rangeStream.ContentRange;
                            rangeContent.Add(rangeBodyPart);
                        }
                        catch (ArgumentOutOfRangeException)
                        {
                            // We ignore range errors until we check that we have at least one valid range
                        }
                    }

                    // If no overlapping ranges were found then stop
                    if (!rangeContent.Any())
                    {
                        ContentRangeHeaderValue actualContentRange = new ContentRangeHeaderValue(content.Length);
                        string msg = Error.Format(Resources.ByteRangeStreamNoneOverlap, range.ToString());
                        throw new InvalidByteRangeException(actualContentRange, msg);
                    }
                }
                else if (range.Ranges.Count == 1)
                {
                    try
                    {
                        ByteRangeStream rangeStream = new ByteRangeStream(content, range.Ranges.First());
                        this._byteRangeContent = new StreamContent(rangeStream, bufferSize);
                        this._byteRangeContent.Headers.ContentType  = mediaType;
                        this._byteRangeContent.Headers.ContentRange = rangeStream.ContentRange;
                    }
                    catch (ArgumentOutOfRangeException)
                    {
                        ContentRangeHeaderValue actualContentRange = new ContentRangeHeaderValue(content.Length);
                        string msg = Error.Format(Resources.ByteRangeStreamNoOverlap, range.ToString());
                        throw new InvalidByteRangeException(actualContentRange, msg);
                    }
                }
                else
                {
                    throw Error.Argument("range", Resources.ByteRangeStreamContentNoRanges);
                }

                // Copy headers from byte range content so that we get the right content type etc.
                this._byteRangeContent.Headers.CopyTo(this.Headers);

                this._content = content;
                this._start   = content.Position;
            }
            catch
            {
                if (this._byteRangeContent != null)
                {
                    this._byteRangeContent.Dispose();
                }
                throw;
            }
        }