是否可以通过ServiceStack在长时间运行的请求上传输部分结果?
问题描述:
我在ServiceStack API上有一个长时间运行的数据库复制请求。完成后,它将返回数据库复制过程的日志。是否可以通过ServiceStack在长时间运行的请求上传输部分结果?
我想响应返回每一行,因为它被添加到包含数据库副本日志的列表对象。
响应将被angular4应用程序接收,所以我猜如果这是可能的,我还需要配置angular4中的某些内容来更改每次响应更新时的状态(ngrx)。
说实话,我不知道从哪里开始。
任何人有任何想法?
答
要流在ServiceStack响应你只需要写入IResponse.OutputStream
直接,你可以在你的服务做的事:
public async Task Any(MyRequest request)
{
foreach (var chunk in Chunks)
await base.Response.OutputStream.WriteAsync(chunk, 0, chunk.Length);
}
或者通过返回实现IStreamWriterAsync
或IStreamWriter
,类似这样的结果:
public class StreamChunksResponse : IStreamWriterAsync
{
public IEnumerable<byte[]>> Chunks { get; set; }
public async Task WriteToAsync(
Stream responseStream,
CancellationToken token = default(CancellationToken))
{
foreach (var chunk in Chunks)
await responseStream.WriteAsync(chunk, 0, chunk.Length);
}
}
哪些将写入响应OutputStream的主机不缓冲响应,对于IIS/ASP.NET,您需要确保Response Buffering is disabled。然后
的问题就变成了如何处理这是要手动需要通过处理响应与readyState == 3
对浏览器的XMLHttpRequest
API编码的客户端,例如在部分反应:
<script>
var xhr = new XMLHttpRequest();
xhr.open('GET', '/stream');
xhr.seenBytes = 0;
xhr.onreadystatechange = function() {
console.log("state change.. state: "+ xhr.readyState);
if(xhr.readyState == 3) {
var newData = xhr.response.substr(xhr.seenBytes);
console.log("newData: <<" +newData+ ">>");
document.body.innerHTML += "New data: <<" +newData+ ">><br />";
xhr.seenBytes = xhr.responseText.length;
console.log("seenBytes: " +xhr.seenBytes);
}
};
xhr.addEventListener("error", function(e) {
console.log("error: " +e);
});
console.log(xhr);
xhr.send();
</script>
这可以让笨拙很快特别是如果您想要传输像JSON这样的序列化格式,那么您需要确保客户端可以构建有效的JSON堆栈。
如果您只是想在客户端下载整个响应时通知客户端更新,我建议您使用类似Server Events的地方,在逐步发送客户端通知更新的同时将响应传输到客户端。
干杯 - 看起来像服务器事件很适合我的要求! – Drammy