Golang http写响应无需等待完成

时间:2017-10-23 12:56:03

标签: go

我正在构建一个构建pdf文件的应用程序,并在收到请求时将其返回给客户端。

由于其中一些pdf文件可能需要一些时间才能生成,我希望在运行时定期向客户端发送某种状态更新。

当它完成构建pdf文件后,它也应该返回给客户端。

类似于:

func buildReport(writer http.ResponseWriter, request *http.Request){
    //build pdf build pdf file
    for { //for example purposes only
        writer.Write([]byte("building. Please wait."))
    }
    pdf.OutputFileAndClose("report.pdf")
    //set header to pdf so that the client knows it's a PDF
    writer.Header().Set("Content-Type", "application/pdf")
    http.ServeFile(writer, request, "report.pdf")
}

func main() {
    http.HandleFunc("/", buildReport)
    http.ListenAndServe(":8081", nil)
}

设置标题可能不起作用,因为编写者只能有一个标题。

3 个答案:

答案 0 :(得分:4)

TL; DR是无法以这种方式实现的。你需要

  1. 请求PDF创建的API。将PDF创建作业排入任务队列(因此​​太多的PDF创建请求不会破坏HTTP服务器工作池)
  2. 提供一个API,允许您检查PDF渲染的位置(我假设作业可以提供临时统计数据)。这将由客户定期进行调查。
  3. 用于在PDF准备就绪后拉取PDF的API。
  4. 希望这对您的项目有所帮助并且好运。

答案 1 :(得分:0)

这绝不是全面的,但可以在此处找到一个合理的示例,说明如何构建API(需要异步,如前一位受访者指出的那样):https://www.adayinthelifeof.nl/2011/06/02/asynchronous-operations-in-rest/

作业队列模型非常常见。我建议你也写一个基本的API绑定库(在任何情况下你都希望这个用于你自己的测试目的),以便你的用户可以理解你打算如何使用API​​,并在编写它时,你&# 39;将更好地了解异步REST交互从最终用户端的感受。

答案 2 :(得分:0)

与其他人所说的相反,事实上你想要的是什么 直接可能但需要完全满足两个先决条件:

  • HTTP / 1.1及以上。
  • 您将向客户发送自定义内容,而不是PDF数据 直接 - 他们准备接受并解析它。

然后,您可以专门使用所谓的“分块”有效负载编码 发明了处理服务器不知道如何的“流式”下载 它将发送许多字节。

因此,您可以定期发明一些有创意的有效载荷 流式传输“无操作”/“进度”标记,然后传输实际有效负载。 比如,在准备文件时,您会定期发送一行文本 阅读“处理”+ LF然后,当结果准备就绪时,您发送 一行文字“READY SIZE + LF其中SIZE是大小,以字节为单位, 紧随其后的PDF文档。文档流后, 服务器发出数据结束信号。

因此流看起来像

PROCESSING
PROCESSING
…
PROCESSING
READY 8388608
%PDF-1.3
…
%%EOF

客户端必须能够从流中解析此信息 他们正在接收并有一个简单的FSM来切换状态 在他们获取你的流时说明。

服务器必须确保在每条“信息”行之后刷新流,否则整个事情就不会是“交互式”。

如果您对处理的整体状态有一个很好的了解 文档,每个“状态更新”行可以包括完成工作的百分比,例如“处理 NN”+ LF