// 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());
}
}
}