Play framework 流的HTTP响应

来源:互联网 发布:怎么在淘宝买小电影 编辑:程序博客网 时间:2024/06/05 06:59

标准响应和HTTP Content-Length头

由于HTTP1.1,保持一个单独的连接打开,以服务多个HTTP请求和响应,服务器必须发送相应的Content-Length头和响应;


默认情况下,当您发送一个简单的结果时,例如:

public static Result index() {    return ok("Hello World");}
你不会指定一个Content-Length头,当然,你发送的内容是众所周知的,Play自动计算内容的大小,并生成合适的头。


注意:基于文本的内容并不像看上去那么简单,由于Content-Length必须根据用于将字符转换为字节的编码来计算。


为了能够正确地计算内容长度头,Play必须消耗整个响应数据并将其内容加载到内存中。


文件服务

如果简单内容将整个内容加载到内存中不是一个问题,那么大数据集呢?假设我们想将一个大文件发送回Web客户机。


Play提供了易于使用的助手来服务本地文件的这项共同任务:

public static Result index() {    return ok(new java.io.File("/tmp/fileToServe.pdf"));}
此外,这个助手还将从文件名中计算Content-Length头。

它还将添加 Content-Dispositon头,指定Web浏览器应该如何处理此响应。默认是要求Web浏览器通过Content-Dispositon下载这个文件


分块响应

目前,这很适合流媒体文件内容。因为我们能够计算流的Content-Length在响应之前。但是,动态计算的内容,没有内容大小可用吗?


这种反应必须使用分块传输编码。

分块传输编码是版本HTTP1.1中的数据传输机制,其中Web服务器以一系列块的方式提供内容。本文采用Transfer-encoding,HTTP响应头而不是Content-Length头,议定书另有规定,因为Content-Length是不被使用的,服务器在开始向客户端发送响应之前不需要知道内容的长度。Web服务器在知道该内容的总大小之前,可以动态生成内容发送响应。每个块的大小是在块本身之前发送的,这样客户端就可以知道它何时完成了对该块的数据接收。数据传输由长度为零的最后一块终止。


其优点是我们可以为数据服务。意思是我们一有数据就发送数据块。缺点是由于Web浏览器不知道内容大小,所以无法显示适当的下载进度条。


我们说,我们有一个服务的地方,提供了一个动态的输入流,计算一些数据。我们可以问起流内容直接采用分块的响应:

public static Result index() {    InputStream is = getDynamicStreamSomewhere();    return ok(is);}
你也可以设置自己的分块响应生成器。Playjava API支持文本和二进制块流;

public static Result index() {    // Prepare a chunked text stream    Chunks<String> chunks = new StringChunks() {        // Called when the stream is ready        public void onReady(Chunks.Out<String> out) {            registerOutChannelSomewhere(out);        }    };    // Serves this stream with 200 OK    return ok(chunks);}
onReady 方法被调用是它是安全的写入该流,它给你一个区块,你可以写信给。

假设我们有一个异步进程(就像一个演员),推到这个流中:

public static void registerOutChannelSomewhere(Chunks.Out<String> out) {    out.write("kiki");    out.write("foo");    out.write("bar");    out.close();}
我们可以检查服务器发送的HTTP响应:

HTTP/1.1 200 OKContent-Type: text/plain; charset=utf-8Transfer-Encoding: chunked4kiki3foo3bar0

我们得到三个块和最后一个空块来关闭响应。

原创粉丝点击