// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.IO; using System.Net.Http.Headers; namespace System.Net.Http { /// /// An suited for writing each MIME body parts of the MIME multipart /// message to a file using a . /// public class MultipartFileStreamProvider : IMultipartStreamProvider { private const int MinBufferSize = 1; private const int DefaultBufferSize = 0x1000; private List _bodyPartFileNames = new List(); private readonly object _thisLock = new object(); private string _rootPath; private int _bufferSize = DefaultBufferSize; /// /// Initializes a new instance of the class. /// /// The root path where the content of MIME multipart body parts are written to. public MultipartFileStreamProvider(string rootPath) : this(rootPath, DefaultBufferSize) { } /// /// Initializes a new instance of the class. /// /// The root path where the content of MIME multipart body parts are written to. /// The number of bytes buffered for writes to the file. public MultipartFileStreamProvider(string rootPath, int bufferSize) { if (String.IsNullOrWhiteSpace(rootPath)) { throw new ArgumentNullException("rootPath"); } if (bufferSize < MinBufferSize) { throw new ArgumentOutOfRangeException("bufferSize", bufferSize, RS.Format(Properties.Resources.ArgumentMustBeGreaterThanOrEqualTo, MinBufferSize)); } _rootPath = Path.GetFullPath(rootPath); _bufferSize = bufferSize; } /// /// Gets an containing the files names of MIME /// body part written to file. /// public Collection BodyPartFileNames { get { lock (_thisLock) { return new Collection(_bodyPartFileNames); } } } /// /// This body part stream provider examines the headers provided by the MIME multipart parser /// and decides which to write the body part to. /// /// Header fields describing the body part /// The instance where the message body part is written to. public virtual Stream GetStream(HttpContentHeaders headers) { if (headers == null) { throw new ArgumentNullException("headers"); } string localFilePath; try { string filename = GetLocalFileName(headers); localFilePath = Path.Combine(_rootPath, Path.GetFileName(filename)); } catch (Exception e) { throw new InvalidOperationException(Properties.Resources.MultipartStreamProviderInvalidLocalFileName, e); } // Add local file name lock (_thisLock) { _bodyPartFileNames.Add(localFilePath); } return File.Create(localFilePath, _bufferSize, FileOptions.Asynchronous); } /// /// Gets the name of the local file which will be combined with the root path to /// create an absolute file name where the contents of the current MIME body part /// will be stored. /// /// The headers for the current MIME body part. /// A relative filename with no path component. public virtual string GetLocalFileName(HttpContentHeaders headers) { if (headers == null) { throw new ArgumentNullException("headers"); } return String.Format(CultureInfo.InvariantCulture, "BodyPart_{0}", Guid.NewGuid()); } } }