// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.ObjectModel; using System.Collections.Specialized; using System.IO; using System.Net.Http.Formatting.Internal; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; using System.Web.Http; namespace System.Net.Http { /// /// A implementation suited for use with HTML file uploads for writing file /// content to a remote storage . The stream provider looks at the Content-Disposition /// header field and determines an output remote based on the presence of a filename /// parameter. If a filename parameter is present in the Content-Disposition header field, then the /// body part is written to a remote provided by . /// Otherwise it is written to a . /// public abstract class MultipartFormDataRemoteStreamProvider : MultipartStreamProvider { private CancellationToken _cancellationToken = CancellationToken.None; /// /// Initializes a new instance of the class. /// protected MultipartFormDataRemoteStreamProvider() { FormData = HttpValueCollection.Create(); FileData = new Collection(); } /// /// Gets a collection of file data passed as part of the multipart form data. /// public Collection FileData { get; private set; } /// /// Gets a of form data passed as part of the multipart form data. /// public NameValueCollection FormData { get; private set; } /// /// Provides a for . Override this method to provide a /// remote stream to which the data should be written. /// /// The parent MIME multipart instance. /// The header fields describing the body part's content. /// /// A result specifying a remote stream where the file will be written to and a location where the file can be /// accessed. It cannot be null and the stream must be writable. /// public abstract RemoteStreamInfo GetRemoteStream(HttpContent parent, HttpContentHeaders headers); /// public override Stream GetStream(HttpContent parent, HttpContentHeaders headers) { if (MultipartFormDataStreamProviderHelper.IsFileContent(parent, headers)) { RemoteStreamInfo remoteStreamInfo = GetRemoteStream(parent, headers); if (remoteStreamInfo == null) { throw Error.InvalidOperation(Properties.Resources.RemoteStreamInfoCannotBeNull, "GetRemoteStream", GetType().Name); } FileData.Add(new MultipartRemoteFileData(headers, remoteStreamInfo.Location, remoteStreamInfo.FileName)); return remoteStreamInfo.RemoteStream; } return new MemoryStream(); } /// /// Read the non-file contents as form data. /// /// A representing the post processing. public override Task ExecutePostProcessingAsync() { // In consistency with existing MultipartFormDataStreamProvider, // this method predates support for cancellation, and we need to make sure it is always invoked when // ExecutePostProcessingAsync is called for compatability. return MultipartFormDataStreamProviderHelper.ReadFormDataAsync(Contents, FormData, _cancellationToken); } /// /// Read the non-file contents as form data. /// /// The token to monitor for cancellation requests. /// A representing the post processing. public override Task ExecutePostProcessingAsync(CancellationToken cancellationToken) { _cancellationToken = cancellationToken; return ExecutePostProcessingAsync(); } } }