是否可以通过ServiceStack在长时间运行的请求上传输部分结果?

是否可以通过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); 
} 

或者通过返回实现IStreamWriterAsyncIStreamWriter,类似这样的结果:

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的地方,在逐步发送客户端通知更新的同时将响应传输到客户端。

+0

干杯 - 看起来像服务器事件很适合我的要求! – Drammy