0

クライアントが選択した利用可能なメカニズムの 1 つによって解析される大きなファイルをアップロードする機能をクライアントに提供する必要がある Web サービスがあります。このサービスの一般的な使用法には、大きなファイルをアップロードし、使用する解析メカニズムを指定することが含まれます。その後、サーバーはアップロードされたデータを解析し、データベースに保存します。

たとえば、有用な情報を含む多数の Excel ファイルがあります。残念ながら、複数の異なる形式があり、それらすべてを解析できる必要があります。現在のソリューションでは、ユーザーが Excel ファイルをアップロードするときに、定義済みの解析方法のリストからも選択するよう求めています。

現在、サービスは次の署名を持つ 1 つのメソッドを提供します。

[OperationContract, WebInvoke(UriTemplate = "/DoUpload/{fileType}")]
void DoUpload(string fileType, Stream fileData);

fileType がクライアントが選択した文字列であり、fileData がクライアントからアップロードされたファイルであるように、Web ベースのクライアント (jQuery を利用する) が DoUpload を呼び出せるようにする何らかの方法が必要です。

理想的には、このメカニズムにより、同じサービスから有効なファイル タイプのリストを公開することもできます。

その他の情報:

  • 他のファイルタイプを含め、将来的に追加のメソッドを追加する必要があります
  • ソリューションはサーバーに C# テクノロジを活用する必要がありますが、必ずしも WCF である必要はありません。
  • アップロードされたファイルはサーバーに保存され、処理後に破棄されます。
4

1 に答える 1

1

WCF は、ストリーミングとバッファリングの 2 つのアップロード方法をサポートしています。Buffered はデフォルトのモードで、ファイル全体をバッファリングし、1 つの大きなチャンクでサーバーに送信します。これは、小規模から中規模のファイルではうまく機能しますが、大きなファイルでは遅すぎる傾向があります。ストリーミングは、サーバーへの多数の応答を介してファイルのビットを送信し、ストリームが中断された場合にストリームを再開する機能など、多くの利点があります。

明らかに、この問題に適切な方法はストリーミングですが、ストリーミングはデフォルトではないため、WCF でストリーミングを使用するには、いくつかの構成作業を行う必要があります。ストリーミングを有効にするには Web.config を変更する必要があるため、この回答は特に WCF サービスに適用されます。

まず、ストリームを受け入れる公開メソッドが 1 つあるとします。たとえば、次のようになります。

[OperationContract]
[WebInvoke(UriTemplate = "/Upload", Method = "POST")]
void Upload(Stream data);

このエンドポイントにストリーミングを使用するように WCF に指示する必要があります。これを行うには、ストリーミングを許可するバインディングが必要です。Web.config で次のようなものを使用できます。

<configuration>
    ...
    <bindings>
        <webHttpBinding>
            <binding name="httpStreamingBinding" transferMode="Streamed" />
        </webHttpBinding>
    </bindings>
    ...
    <services>
        <service name="MyServiceNamespace.MyServiceName">
            <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding"
                      bindingConfiguration="httpStreamingBinding" name="UploadEndpoint"
                      contract="MyServiceNamespace.IMyServiceName" />
        </service>
    </services>
    ...
    <behaviors>
        ...
        <endpointBehaviors>
            <behavior name="web">
                <webHttp />
            </behavior>
        </endpointBehaviors>
    </behaviors>
</configuration>

これにより、Upload メソッドを含むクラスを指すエンドポイントが作成され、ストリーミング転送を使用するように構成されます。しかし、まだ問題があります。大きなファイルの転送には時間がかかります。また、Web サーバーの既定のタイムアウトが小さすぎて大きなファイルを転送できないため、Web.config をさらに変更する必要があります。

最初に、httpStreamingBinding のタイムアウトの長さと最大受信メッセージ サイズを次のように変更する必要があります (maxRecievedMessageSize はバイト単位です)。

<binding name="httpStreamingBinding" maxReceivedMessageSize="4294967296"
         transferMode="Streamed" 
         crossDomainScriptAccessEnabled="true"
         openTimeout="00:01:00"
         closeTimeout="00:01:00"
         receiveTimeout="02:00:00"
         sendTimeout="02:00:00"
         />

次に、大きなファイルを受け入れるように http ランタイムを変更する必要があります。ここでは、最大値として 4 GB を選択しました (maxRequestLength は kb 単位)。

<system.web>
    ...    
    <httpRuntime
      executionTimeout="7200" 
      maxRequestLength="4194304" />
</system.web>

これでストリーミング データを受信できるようになりましたが、まだやるべきことがあります。通常、大規模な HTTP アップロードは multipart/form-data コンテンツ タイプを使用して行われます。これは、ストリームで受信するデータが、アップロードされたファイルだけでなく、フォームからの追加データであることを意味します。このデータを手動で解析することも、既存のパーサーを使用することもできます。Lorenzo は、この回答で優れたマルチパート データ パーサーを提供しています。

マルチパート データのアップロードは HTML フォームを使用すると簡単ですが、JavaScript を使用したい場合はどうすればよいでしょうか。ブラウザーに応じて、ストリーミング データのアップロードにはさまざまなレベルのサポートがありますが、jQuery ファイル アップローダー プラグインは、ストリーミング データ サービスにファイルをアップロードするための優れたサポートを提供します。次のように、マルチパート パーサーのファイル名として「files[]」を必ず使用してください。

[OperationContract]
[WebInvoke(UriTemplate = "/Upload", Method = "POST")]
void Upload(Stream data)
{
    var parser = new HttpMultipartParser(data, "files[]");
    ...
}

データを取得したので、アップロードされたファイルのタイプに基づいて何らかのロジックを実行する方法が必要です。URL パラメータに基づいて解析方法を変更することでこれを解決しました。たとえば、/Upload/FormatOne は FormatOne メソッドを使用し、/Upload/FormatTwo は FormatTwo を使用します。これは、次の方法を使用して実現されます。

delegate void FileFormatHandler(Stream data);

[OperationContract]
[WebInvoke(UriTemplate = "/Upload/{fileType}", Method = "POST")]
void Upload(string fileType, Stream data)
{
    var parser = new HttpMultipartParser(data, "files[]");

    FileFormatHandler handler = selectHandler(fileType);
    handler(data);
}

残念ながら、このメソッドは、Stream が SOAP の唯一の引数であると想定されているため、サービスが SOAP ベースの WCF 呼び出しメカニズムで機能しなくなることを意味しますが、Web 呼び出しはこの制限の影響を受けません。

これで、ストリーミングを使用して大きなファイルを受け入れ、ユーザーが使用する URL に基づいてさまざまな解析メソッドを呼び出すことができる WCF サービスができました。データをアップロードするには、ユーザーは適切な URL に情報を POST するだけです。たとえば、ユーザーがファイルをアップロードして MyFancyFormat パーサーで解析したい場合、次の URL に POST します。

http://myserver/MyService.svc/Upload/MyFancyFormat
于 2012-12-19T01:13:52.690 に答える