// 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.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Net.Http.Headers; using System.Net.Http.Internal; using System.Web.Http; namespace System.Net.Http { /// /// A suited for writing each MIME body parts of the MIME multipart /// message to a file using a . /// public class MultipartFileStreamProvider : MultipartStreamProvider { private const int MinBufferSize = 1; private const int DefaultBufferSize = 0x1000; private string _rootPath; private int _bufferSize = DefaultBufferSize; private Collection _fileData = new Collection(); /// /// 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 a file. public MultipartFileStreamProvider(string rootPath, int bufferSize) { if (rootPath == null) { throw Error.ArgumentNull("rootPath"); } if (bufferSize < MinBufferSize) { throw Error.ArgumentMustBeGreaterThanOrEqualTo("bufferSize", bufferSize, MinBufferSize); } _rootPath = Path.GetFullPath(rootPath); _bufferSize = bufferSize; } /// /// Gets a collection containing the local files names and associated HTTP content headers of MIME /// body parts written to file. /// public Collection FileData { get { return _fileData; } } /// /// Gets the root path where the content of MIME multipart body parts are written to. /// protected string RootPath { get { return _rootPath; } } /// /// Gets the number of bytes buffered for writes to a file. /// protected int BufferSize { get { return _bufferSize; } } [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Stream is closed by caller (MultipartWriteDelegatingStream is just a wrapper that calls into the inner stream.)")] public override Stream GetStream(HttpContent parent, HttpContentHeaders headers) { if (parent == null) { throw Error.ArgumentNull("parent"); } if (headers == null) { throw Error.ArgumentNull("headers"); } string localFilePath; try { string filename = GetLocalFileName(headers); localFilePath = Path.Combine(_rootPath, Path.GetFileName(filename)); } catch (Exception e) { throw Error.InvalidOperation(e, Properties.Resources.MultipartStreamProviderInvalidLocalFileName); } // Add local file name MultipartFileData fileData = new MultipartFileData(headers, localFilePath); _fileData.Add(fileData); 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 Error.ArgumentNull("headers"); } return String.Format(CultureInfo.InvariantCulture, "BodyPart_{0}", Guid.NewGuid()); } } }