ServiceStack服务中是否有任何机制可以返回流/大二进制数据? WCF的MTOM支持很难但在返回大量数据时却没有文本转换开销。
答案 0 :(得分:18)
我喜欢服务堆栈,这个litle代码足以从内存流中返回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();
}
}
答案 1 :(得分:16)
从鸟瞰图ServiceStack可以返回以下任何一个:
以下类型未转换并直接写入响应流:
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响应状态代码。您可以参考HttpResult对象的实现,以实现上述接口的实际实现。
答案 2 :(得分: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”中借用:Copy a Stream with Progress Reporting(感谢Henning Dieterichs)
感谢mythz和ServiceStack的任何贡献者。伟大的项目!