public static Task <IEnumerable <HttpContent> > ReadAsMultipartAsync(this HttpContent content, IMultipartStreamProvider streamProvider, int bufferSize) { if (content == null) { throw new ArgumentNullException("content"); } if (streamProvider == null) { throw new ArgumentNullException("streamProvider"); } if (bufferSize < MinBufferSize) { throw new ArgumentOutOfRangeException("bufferSize", bufferSize, RS.Format(Properties.Resources.ArgumentMustBeGreaterThanOrEqualTo, MinBufferSize)); } return(content.ReadAsStreamAsync().Then(stream => { TaskCompletionSource <IEnumerable <HttpContent> > taskCompletionSource = new TaskCompletionSource <IEnumerable <HttpContent> >(); MimeMultipartBodyPartParser parser = new MimeMultipartBodyPartParser(content, streamProvider); byte[] data = new byte[bufferSize]; MultipartAsyncContext context = new MultipartAsyncContext(stream, taskCompletionSource, parser, data); // Start async read/write loop MultipartReadAsync(context); // Return task and complete later return taskCompletionSource.Task; })); }
/// <summary> /// Determines whether the specified content is MIME multipart content. /// </summary> /// <param name="content">The content.</param> /// <returns> /// <c>true</c> if the specified content is MIME multipart content; otherwise, <c>false</c>. /// </returns> public static bool IsMimeMultipartContent(this HttpContent content) { if (content == null) { throw Error.ArgumentNull("content"); } return(MimeMultipartBodyPartParser.IsMimeMultipartContent(content)); }
/// <summary> /// Reads all body parts within a MIME multipart message using the provided <see cref="MultipartStreamProvider"/> instance /// to determine where the contents of each body part is written and <paramref name="bufferSize"/> as read buffer size. /// </summary> /// <typeparam name="T">The <see cref="MultipartStreamProvider"/> with which to process the data.</typeparam> /// <param name="content">An existing <see cref="HttpContent"/> instance to use for the object's content.</param> /// <param name="streamProvider">A stream provider providing output streams for where to write body parts as they are parsed.</param> /// <param name="bufferSize">Size of the buffer used to read the contents.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <returns>A <see cref="Task{T}"/> representing the tasks of getting the result of reading the MIME content.</returns> public static async Task <T> ReadAsMultipartAsync <T>( this HttpContent content, T streamProvider, int bufferSize, CancellationToken cancellationToken ) where T : MultipartStreamProvider { if (content == null) { throw Error.ArgumentNull("content"); } if (streamProvider == null) { throw Error.ArgumentNull("streamProvider"); } if (bufferSize < MinBufferSize) { throw Error.ArgumentMustBeGreaterThanOrEqualTo( "bufferSize", bufferSize, MinBufferSize ); } Stream stream; try { stream = await content.ReadAsStreamAsync(); } catch (Exception e) { throw new IOException(Properties.Resources.ReadAsMimeMultipartErrorReading, e); } using (var parser = new MimeMultipartBodyPartParser(content, streamProvider)) { byte[] data = new byte[bufferSize]; MultipartAsyncContext context = new MultipartAsyncContext( stream, parser, data, streamProvider.Contents ); // Start async read/write loop await MultipartReadAsync(context, cancellationToken); // Let the stream provider post-process when everything is complete await streamProvider.ExecutePostProcessingAsync(cancellationToken); return(streamProvider); } }
public MultipartAsyncContext(Stream contentStream, MimeMultipartBodyPartParser mimeParser, byte[] data, ICollection <HttpContent> result) { Contract.Assert(contentStream != null); Contract.Assert(mimeParser != null); Contract.Assert(data != null); ContentStream = contentStream; Result = result; MimeParser = mimeParser; Data = data; }
/// <summary> /// Initializes a new instance of the <see cref="MultipartAsyncContext"/> class. /// </summary> /// <param name="contentStream">The content stream.</param> /// <param name="taskCompletionSource">The task completion source.</param> /// <param name="mimeParser">The MIME parser.</param> /// <param name="data">The buffer that we read data from.</param> public MultipartAsyncContext(Stream contentStream, TaskCompletionSource <IEnumerable <HttpContent> > taskCompletionSource, MimeMultipartBodyPartParser mimeParser, byte[] data) { Contract.Assert(contentStream != null, "contentStream cannot be null"); Contract.Assert(taskCompletionSource != null, "task cannot be null"); Contract.Assert(mimeParser != null, "mimeParser cannot be null"); Contract.Assert(data != null, "data cannot be null"); ContentStream = contentStream; Result = new List <HttpContent>(); TaskCompletionSource = taskCompletionSource; MimeParser = mimeParser; Data = data; }
public MultipartAsyncContext(HttpContent parent, Stream contentStream, TaskCompletionSource <bool> taskCompletionSource, MimeMultipartBodyPartParser mimeParser, byte[] data, ICollection <HttpContent> result) { Contract.Assert(parent != null); Contract.Assert(contentStream != null); Contract.Assert(taskCompletionSource != null); Contract.Assert(mimeParser != null); Contract.Assert(data != null); Parent = parent; ContentStream = contentStream; Result = result; TaskCompletionSource = taskCompletionSource; MimeParser = mimeParser; Data = data; }
public static Task <T> ReadAsMultipartAsync <T>(this HttpContent content, T streamProvider, int bufferSize) where T : MultipartStreamProvider { if (content == null) { throw Error.ArgumentNull("content"); } if (streamProvider == null) { throw Error.ArgumentNull("streamProvider"); } if (bufferSize < MinBufferSize) { throw Error.ArgumentMustBeGreaterThanOrEqualTo("bufferSize", bufferSize, MinBufferSize); } MimeMultipartBodyPartParser parser = null; return(content.ReadAsStreamAsync().Then(stream => { TaskCompletionSource <bool> taskCompletionSource = new TaskCompletionSource <bool>(); parser = new MimeMultipartBodyPartParser(content, streamProvider); byte[] data = new byte[bufferSize]; MultipartAsyncContext context = new MultipartAsyncContext(content, stream, taskCompletionSource, parser, data, streamProvider.Contents); // Start async read/write loop MultipartReadAsync(context); // Return task and complete when we have run the post processing step. return taskCompletionSource.Task.Then(() => streamProvider.ExecutePostProcessingAsync().ToTask <T>(result: streamProvider)); }).Finally(() => { if (parser != null) { parser.Dispose(); } }, runSynchronously: true)); }
/// <summary> /// Reads all body parts within a MIME multipart message using the provided <see cref="MultipartStreamProvider"/> instance /// to determine where the contents of each body part is written and <paramref name="bufferSize"/> as read buffer size. /// </summary> /// <typeparam name="T">The <see cref="MultipartStreamProvider"/> with which to process the data.</typeparam> /// <param name="content">An existing <see cref="HttpContent"/> instance to use for the object's content.</param> /// <param name="streamProvider">A stream provider providing output streams for where to write body parts as they are parsed.</param> /// <param name="bufferSize">Size of the buffer used to read the contents.</param> /// <returns>A <see cref="Task{T}"/> representing the tasks of getting the result of reading the MIME content.</returns> #if NETFX_CORE public static async Task <T> ReadAsMultipartAsync <T>(this HttpContent content, T streamProvider, int bufferSize) where T : MultipartStreamProvider { if (content == null) { throw Error.ArgumentNull("content"); } if (streamProvider == null) { throw Error.ArgumentNull("streamProvider"); } if (bufferSize < MinBufferSize) { throw Error.ArgumentMustBeGreaterThanOrEqualTo("bufferSize", bufferSize, MinBufferSize); } try { Stream stream = await content.ReadAsStreamAsync(); List <HttpContent> childContents = new List <HttpContent>(); using (var parser = new MimeMultipartBodyPartParser(content, streamProvider)) { byte[] buffer = new byte[bufferSize]; bool finalPart = false; while (!finalPart) { int readCount = await stream.ReadAsync(buffer, 0, buffer.Length); // The parser returns one or more parsed parts, depending on how much data was returned // from the network read. The last part may be incomplete (partial), so we only dispose // of the parts once we know they're finished. Regardless of whether the part is complete // or not, we send the bytes to the desired output stream. We loop back for more data // until we've completely read the complete, final part. foreach (MimeBodyPart part in parser.ParseBuffer(buffer, readCount)) { try { Stream output = part.GetOutputStream(content); foreach (ArraySegment <byte> segment in part.Segments) { await output.WriteAsync(segment.Array, segment.Offset, segment.Count); } if (part.IsComplete) { if (part.HttpContent != null) { childContents.Add(part.HttpContent); } finalPart = part.IsFinal; part.Dispose(); break; } } catch (Exception) { // Clean up the part if we got an error in the middle of parsing, because we normally // won't dispose a part until it's complete. part.Dispose(); throw; } } } // Let the stream provider post-process when everything is complete await streamProvider.ExecutePostProcessingAsync(); return(streamProvider); } } catch (Exception e) { throw new IOException(Properties.Resources.ReadAsMimeMultipartErrorReading, e); } }