15

ServiceStack サービスにストリーミング/大きなバイナリ データを返すメカニズムはありますか? WCF の MTOM サポートは扱いにくいですが、テキスト変換のオーバーヘッドなしで大量のデータを返すのに効果的です。

4

3 に答える 3

19

私はサービス スタックが大好きです。メモリ ストリームから Excel レポートを返すには、この小さなコードで十分でした。

public class ExcelFileResult : IHasOptions, IStreamWriter
{
    private readonly Stream _responseStream;
    public IDictionary<string, string> Options { get; private set; }

    public ExcelFileResult(Stream responseStream)
    {
        _responseStream = responseStream;

        Options = new Dictionary<string, string> {
             {"Content-Type", "application/octet-stream"},
             {"Content-Disposition", "attachment; filename=\"report.xls\";"}
         };
    }

    public void WriteTo(Stream responseStream)
    {
        if (_responseStream == null) 
            return;

        _responseStream.WriteTo(responseStream);
        responseStream.Flush();
    }
}
于 2012-03-23T17:18:14.160 に答える
16

概観すると、ServiceStackは次のいずれかを返すことができます。

  • 任意の DTO オブジェクト -> Response ContentType にシリアル化
  • カスタマイズされた HTTP 応答の HttpResult、HttpError、CompressedResult (IHttpResult)

次の型は変換されず、応答ストリームに直接書き込まれます。

  • ストリーム
  • IStreamWriter
  • byte[] -application/octet-streamコンテンツ タイプ。

詳細

プレーンな C# オブジェクトを返すだけでなく、ServiceStack を使用すると、任意のStreamまたは IStreamWriter を返すことができます (応答ストリームへの書き込み方法が少し柔軟になります)。

public interface IStreamWriter
{
    void WriteTo(Stream stream);
}

ただし、どちらも追加の変換オーバーヘッドなしで Response OutputStream に直接書き込むことができます。

同時に HTTP ヘッダーをカスタマイズする場合は、ディクショナリ エントリが応答 HttpHeaders に書き込まれるIHasOptionsを実装する必要があります。

public interface IHasOptions
{
    IDictionary<string, string> Options { get; }
}

さらに、IHttpResult を使用すると、カスタムの HTTP 応答ステータス コードを指定できる HTTP 出力をさらに細かく制御できます。上記のインターフェイスの実際の実装については、 HttpResultオブジェクトの実装を参照できます。

于 2011-06-06T07:44:10.947 に答える
4

同様の要件があり、ストリーミング ファイルのダウンロードの進行状況も追跡する必要がありました。私は大まかに次のようにしました:

サーバー側:

サービス:

public object Get(FooRequest request)
{
    var stream = ...//some Stream
    return new StreamedResult(stream);
}

StreamedResult クラス:

public class StreamedResult : IHasOptions, IStreamWriter
{
    public IDictionary<string, string> Options { get; private set; }
    Stream _responseStream;

    public StreamedResult(Stream responseStream)
    {
        _responseStream = responseStream;

        long length = -1;
        try { length = _responseStream.Length; }
        catch (NotSupportedException) { }

        Options = new Dictionary<string, string>
        {
            {"Content-Type", "application/octet-stream"},
            { "X-Api-Length", length.ToString() }
        };
    }

    public void WriteTo(Stream responseStream)
    {
        if (_responseStream == null)
            return;

        using (_responseStream)
        {
            _responseStream.WriteTo(responseStream);
            responseStream.Flush();
        }
    }
}

クライアント側:

string path = Path.GetTempFileName();//in reality, wrap this in try... so as not to leave hanging tmp files
var response = client.Get<HttpWebResponse>("/foo/bar");

long length;
if (!long.TryParse(response.GetResponseHeader("X-Api-Length"), out length))
    length = -1;

using (var fs = System.IO.File.OpenWrite(path))
    fs.CopyFrom(response.GetResponseStream(), new CopyFromArguments(new ProgressChange((x, y) => { Console.WriteLine(">> {0} {1}".Fmt(x, y)); }), TimeSpan.FromMilliseconds(100), length));

「CopyFrom」拡張メソッドは、このプロジェクトのソース コード ファイル「StreamHelper.cs」から直接借用したものです:進行状況レポートを使用してストリームをコピーする(Henning Dieterichs に敬意を表します)

そして、mythz と ServiceStack への貢献者に敬意を表します。素晴らしいプロジェクトです!

于 2013-10-08T15:34:42.757 に答える