【问题标题】:Stream output of command to ajax call with ServiceStack使用 ServiceStack 将命令的流输出流式传输到 ajax 调用
【发布时间】:2017-09-29 01:26:16
【问题描述】:

我有一个 ServiceStack 服务,它在给定输入文件的情况下在后台执行一个长时间运行(如 10-20 秒)的程序。在客户端,文件被上传到服务,然后文件被传递给可执行文件。我有能力将该可执行文件的输出重定向到一个流,但是当我尝试将该流发送到客户端的 ajax 调用时,它不会开始消耗,直到流完成。我认为我已经正确完成了设置部分内容的所有操作,所以我不确定为什么这不起作用(或者如果这甚至可以通过服务器端的 ServiceStack 和 jQuery 的 ajax在客户端调用)。我的代码如下(稍作修改以删除任何专有内容。但同样的原则适用):

//Service side
public async Task<HttpResult> Post(SomeProcessingRequest request) {
    var tempFile = Path.GetTempFileName();
    try {
        base.Request.Files.FirstNonDefault().SaveTo(tempFile);
        log.Info($@"Launching application");
        var ms = new MemoryStream();
        var sw = new StreamWriter(ms);
        var result = new HttpResult(ms, "text");
        //launches the app and pipes the output to the lambda (just a wrapper for Process)
        await env.LaunchApplication("myapp.exe", false, (msg) => {
            if (msg != null) {
                ms.Write(msg);
                ms.Flush();
            }
        }, (msg) => {}, () => { }, () => { throw new Exception("application failed"); }, $@"-i {tempFile}");
        log.Info($@"app complete");
        return result;
    } finally {
        try {
            File.Delete(tempFile);
        } catch(IOException ex) {
            log.Warn($@"Could not delete temp file {tempFile}");
        }
    }
}

和客户端ajax调用:

this.ImportCommand = (element, event) => {
    var last_response_len = false;
    var fileInput = $('#fileInput');
    var file = fileInput.get(0).files[0];
    var formData = new FormData();
    formData.append('file', file);
    $.ajax({
        url: `/*url here*/`,
        type: 'POST',
        data: formData,
        cache: false,
        contentType: false,
        processData: false,
        success: (res) => {
            console.log("app call complete");
            self.RefreshCommand();
        },
        xhrFields: {
            onprogress: (e) => {
                console.log(e.currentTarget.response);
                var this_response, response = e.currentTarget.response;
                if (last_response_len === false) {
                    this_response = response;
                    last_response_len = response.length;
                } else {
                    this_response = response.substring(last_response_len);
                    last_response_len = response.length;
                }
                self.outputLog += this_response;
            }
        }
    });

因此,一切似乎都正常工作,除了不是实时流式传输命令的输出,而是将其全部添加到流中,然后在响应来自服务器时转储流。我试图通过 ServiceStack/jQuery 实现的目标是什么?本质上,我想展示一些类似于 Jenkins 构建日志实时更新的内容。

【问题讨论】:

    标签: c# jquery ajax servicestack


    【解决方案1】:

    感谢 Petah 在这里的评论,我明白了:jquery ajax, read the stream incrementally?

    问题在于它一次写入的字节数少于 2048 个字节。只是为了好玩和咯咯笑,我创建了一个 4096 字节的数组,并多次将其写出,并睡了几次,果然它按预期工作。我花的时间比我应该做的要长得多......

    【讨论】:

    • 我应该说,我还必须直接写入 Response.OutputStream 而不是使用 MemoryStream。我认为那是犹太教。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-02
    相关资源
    最近更新 更多