¿ServiceStack admite respuestas binarias?

¿Hay algún mecanismo en los servicios de ServiceStack para devolver la transmisión / grandes datos binarios? El soporte MTOM de WCF es incómodo pero efectivo para devolver grandes cantidades de datos sin sobrecarga de conversión de texto.

Desde una vista de pájaro, ServiceStack puede devolver cualquiera de:

  • Cualquier objeto DTO -> serializado a Response ContentType
  • HttpResult, HttpError, CompressedResult (IHttpResult) para una respuesta HTTP personalizada

Los siguientes tipos no se convierten y se escriben directamente en la secuencia de respuesta:

  • Cuerda
  • Corriente
  • IStreamWriter
  • byte [] – con el tipo de contenido application/octet-stream .

Detalles

Además de devolver objetos simples C #, ServiceStack le permite devolver cualquier Stream o IStreamWriter (que es un poco más flexible sobre cómo escribe en la secuencia de respuesta):

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

Sin embargo, ambos le permiten escribir directamente en Response OutputStream sin ninguna sobrecarga de conversión adicional.

Si desea personalizar los encabezados HTTP al mismo tiempo, solo necesita implementar IHasOptions donde se escribe cualquier Entrada de diccionario en Response HttpHeaders.

 public interface IHasOptions { IDictionary Options { get; } } 

Más allá de eso, IHttpResult permite un control incluso más fino de la salida HTTP donde puede suministrar un código de estado de respuesta Http personalizado. Puede consultar la implementación del objeto HttpResult para una implementación en el mundo real de estas interfaces anteriores.

Me encanta la stack de servicios, este pequeño código fue suficiente para devolver un informe de Excel de la secuencia de la memoria

 public class ExcelFileResult : IHasOptions, IStreamWriter { private readonly Stream _responseStream; public IDictionary Options { get; private set; } public ExcelFileResult(Stream responseStream) { _responseStream = responseStream; Options = new Dictionary { {"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(); } } 

Tenía un requisito similar que también requería que rastreara el progreso de la descarga del archivo de transmisión. Lo hice más o menos así:

lado del servidor :

Servicio:

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

Clase StreamedResult:

 public class StreamedResult : IHasOptions, IStreamWriter { public IDictionary Options { get; private set; } Stream _responseStream; public StreamedResult(Stream responseStream) { _responseStream = responseStream; long length = -1; try { length = _responseStream.Length; } catch (NotSupportedException) { } Options = new Dictionary { {"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(); } } } 

lado del cliente :

 string path = Path.GetTempFileName();//in reality, wrap this in try... so as not to leave hanging tmp files var response = client.Get("/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)); 

El método de extensión “CopyFrom” se tomó prestado directamente del archivo de código fuente “StreamHelper.cs” en este proyecto aquí: Copiar una secuencia con informes de progreso (Felicitaciones a Henning Dieterichs)

Y felicitaciones a mythz y a cualquier colaborador de ServiceStack. ¡Gran proyecto!