2013-04-05 32 views
28

私はクライアント(HTMLページとiPhoneアプリ)が画像をアップロードできるようにするASP.Net Web APIアプリケーションを持っています。このarticleに記載されている非同期アップロードタスクを使用しています。MultipartFormDataStreamProviderをオーバーライドして、ファイルシステムにアップロードを保存しないようにすることはできますか?

ファイルシステムに保存したいときは、このコードが自動的に実行するので、すべてがうまくいくように見えます。しかし、私はアップロードされたファイルをファイルシステムに保存したくありません。代わりに、アップロードしたストリームをAWS SDK for .Netを使用してAmazon S3バケットに渡したいと思っています。

AWSにストリームを送信するようにコードを設定しました。私が理解できない問題は、アップロードされたコンテンツストリームを自動的にディスクに保存するのではなく、Web APIメソッドから取得する方法です。

私は私がディスクに保存する以外にアップロードされたコンテンツを他の何かを行うことができるようになる私はMultipartFormDataStreamProviderにオーバーライドすることができます仮想メソッドになりますが期待していたが、があるようには思えません。

提案がありますか?

+0

こんにちは、それは古い質問ですが、それは私を多く助けました。 AWSストリームを作成するための完全なコードを投稿することもできますか?私はAWSストリームを以下の受け入れられた答えで返す方法、または後でそれをどうするかを理解できません。 – l3utterfly

答えて

41

MultipartFormDataStreamProviderのGetStreamメソッドをオーバーライドしてファイルストリームではなくAWSストリームのストリームを返すことができますが、いくつかの問題があります(ここでは詳しく説明しません)。代わりに抽象基本クラスMultipartStreamProviderから派生したプロバイダを作成できます。次のサンプルは、MultipartFormDataStreamProviderとMultipartFileStreamProviderの実際のソースコードに大きく基づいています。詳細はhereおよびhereを確認することができます。以下のサンプル:@KiranChallaは自分の答えを掲示しているので

public class CustomMultipartFormDataStreamProvider : MultipartStreamProvider 
{ 
    private NameValueCollection _formData = new NameValueCollection(StringComparer.OrdinalIgnoreCase); 

    private Collection<bool> _isFormData = new Collection<bool>(); 

    private Collection<MyMultipartFileData> _fileData = new Collection<MyMultipartFileData>(); 

    public NameValueCollection FormData 
    { 
     get { return _formData; } 
    } 

    public Collection<MultipartFileData> FileData 
    { 
     get { return _fileData; } 
    } 

    public override Stream GetStream(HttpContent parent, HttpContentHeaders headers) 
    { 
     // For form data, Content-Disposition header is a requirement 
     ContentDispositionHeaderValue contentDisposition = headers.ContentDisposition; 
     if (contentDisposition != null) 
     { 
      // If we have a file name then write contents out to AWS stream. Otherwise just write to MemoryStream 
      if (!String.IsNullOrEmpty(contentDisposition.FileName)) 
      { 
       // We won't post process files as form data 
       _isFormData.Add(false); 

       MyMultipartFileData fileData = new MyMultipartFileData(headers, your-aws-filelocation-url-maybe); 
       _fileData.Add(fileData); 

       return myAWSStream;//**return you AWS stream here** 
      } 

      // We will post process this as form data 
      _isFormData.Add(true); 

      // If no filename parameter was found in the Content-Disposition header then return a memory stream. 
      return new MemoryStream(); 
     } 

     throw new InvalidOperationException("Did not find required 'Content-Disposition' header field in MIME multipart body part.."); 
    } 

    /// <summary> 
    /// Read the non-file contents as form data. 
    /// </summary> 
    /// <returns></returns> 
    public override async Task ExecutePostProcessingAsync() 
    { 
     // Find instances of HttpContent for which we created a memory stream and read them asynchronously 
     // to get the string content and then add that as form data 
     for (int index = 0; index < Contents.Count; index++) 
     { 
      if (_isFormData[index]) 
      { 
       HttpContent formContent = Contents[index]; 
       // Extract name from Content-Disposition header. We know from earlier that the header is present. 
       ContentDispositionHeaderValue contentDisposition = formContent.Headers.ContentDisposition; 
       string formFieldName = UnquoteToken(contentDisposition.Name) ?? String.Empty; 

       // Read the contents as string data and add to form data 
       string formFieldValue = await formContent.ReadAsStringAsync(); 
       FormData.Add(formFieldName, formFieldValue); 
      } 
     } 
    } 

    /// <summary> 
    /// Remove bounding quotes on a token if present 
    /// </summary> 
    /// <param name="token">Token to unquote.</param> 
    /// <returns>Unquoted token.</returns> 
    private static string UnquoteToken(string token) 
    { 
     if (String.IsNullOrWhiteSpace(token)) 
     { 
      return token; 
     } 

     if (token.StartsWith("\"", StringComparison.Ordinal) && token.EndsWith("\"", StringComparison.Ordinal) && token.Length > 1) 
     { 
      return token.Substring(1, token.Length - 2); 
     } 

     return token; 
    } 
} 

public class MyMultipartFileData 
{ 
    public MultipartFileData(HttpContentHeaders headers, string awsFileUrl) 
    { 
     Headers = headers; 
     AwsFileUrl = awsFileUrl; 
    } 

    public HttpContentHeaders Headers { get; private set; } 

    public string AwsFileUrl { get; private set; } 
} 
+1

Brilliant!あなたは私が物事を非常に理解するのを手伝ってくれました。まず最初に、ファイルが実際にディスクに保存される方法(これはこれまで私には分かっていなかった)を見ています。 MultipartFileStreamProviderのGetStream(これは、私のカスタムプロバイダが派生しているMultipartFormDataStreamProviderのベースです)で発生しています。さて、私ができることは、MultipartStreamProviderから直接派生し、GetStreamをオーバーライドして、ディスクに保存せず、S3にコミットするようにすることです。どうもありがとう! – Stoop

+5

ストリームがmyAWSStreamに書き込まれる部分を明確にしたいと思っています。 AWSの代わりにAzure Blobストレージに何かを書きたいと思います。しかし、私は(メソッドGetStreamで)どのようにストリームにアクセスするのかわかりません。このメソッドで私はしたいと思います:BlobService.StoreImageToBlobFromStream(stream) – woutercx

+3

解決策は、 "このクラスのコードを読み込み、このクラスのコードをコピーして独自のクラスを作成しましょう"と表示されているため、 – mwardm

2

は、新しい抽象クラスMultipartFormDataRemoteStreamProviderが、これは容易にするためにFix 1760: Make MultipartFormDataStreamProvider easier to work with non-FileStreams.で導入されました。

クラスの概要は、それを使用する方法を説明するのに良い仕事をしていません:リモートストレージStreamにファイルの内容を記述するためのHTMLファイルのアップロードでの使用に適し

MultipartStreamProvider実装。ストリームプロバイダは、Content-Dispositionヘッダフィールドを調べ、ファイル名パラメータの存在に基づいて、リモートの出力をStreamに決定します。ファイル名パラメータがContent-Dispositionヘッダーフィールドに存在する場合、本文部分はGetRemoteStreamによって提供されるリモートStreamに書き込まれます。それ以外の場合はMemoryStreamに書き込まれます。

関連する問題