ServiceStack поддерживает бинарные ответы? - PullRequest
15 голосов
/ 06 июня 2011

Есть ли в службах ServiceStack какой-либо механизм для возврата потоковых / больших двоичных данных? Поддержка MTOM в WCF неудобна, но эффективна при возврате больших объемов данных без необходимости преобразования текста.

Ответы [ 3 ]

18 голосов
/ 23 марта 2012

Мне нравится стек обслуживания, этого маленького кода было достаточно, чтобы вернуть отчет 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();
    }
}
16 голосов
/ 06 июня 2011

С высоты птичьего полета ServiceStack может возвращать любой из:

  • Любой объект DTO -> сериализован в ответ ContentType
  • HttpResult, HttpError, CompressedResult(IHttpResult) для настраиваемого ответа HTTP

Следующие типы не преобразуются и записываются непосредственно в поток ответов:

  • Строка
  • Поток
  • IStreamWriter
  • byte [] - с типом содержимого application/octet-stream.

Подробности

В дополнение к возврату простых объектов C #, ServiceStack позволяет вамчтобы вернуть любой Stream или IStreamWriter (который немного более гибок в том, как вы пишете в поток ответов):

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

Оба позволяют вам записывать напрямую в Response OutputStream безлюбые дополнительные издержки преобразования.

Если вы хотите настроить заголовки HTTP одновременно, вам просто нужно реализовать IHasOptions , где любая запись словаря записывается в Response HttpHeaders.

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

Более того, IHttpResult позволяет даже более детальное управление выводом HTTP, где вы можете предоставить собственный код состояния Http Response.Вы можете обратиться к реализации HttpResult объекта для реальной реализации этих вышеупомянутых интерфейсов.

4 голосов
/ 08 октября 2013

У меня было похожее требование, которое также требовало от меня отслеживания прогресса загрузки потокового файла. Я сделал это примерно так:

на стороне сервера :

обслуживание:

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» в этом проекте здесь: Копирование потока с отчетом о ходе выполнения (Слава Хеннингу Дитрихсу)

И похвала мифу и любому вкладчику ServiceStack. Отличный проект!

...