Play Framework 2.8.19:WS流式传输大响应失效问题求助
问题解决:Play框架2.8.19流式传输大响应失效
问题场景
尝试从远程服务器流式传输大文件(如维基媒体的大尺寸图片),预期将内容分块返回给客户端,但实际会加载完整文件后才发送。即使照搬Play官方文档中的流式处理代码,问题依然存在,代码如下:
Action.async { implicit request => val futureResponse = ws.url( "https://upload.wikimedia.org/wikipedia/commons/c/c7/%2271%22_on_St._Patrick%27s_Day._Washington%2C_D.C.%2C_March_17._" + "Justice_Pierce_Butler%2C_71_years_old_today_celebrates_his_birthday_by_taking_his_morning_walk%2C_snapped_while_leaving_his_home_on_19" + "th_LCCN2016871374.tif") .withMethod("GET") .stream() futureResponse.map { f => Ok.chunked(f.bodyAsSource) } }
原因排查与解决方案
1. 禁用WS客户端响应缓存
Play WS客户端默认可能会缓存完整响应,即便调用了stream()方法。需显式添加请求头禁用缓存:
val futureResponse = ws.url(imageUrl) .withMethod("GET") .withHttpHeaders("Cache-Control" -> "no-cache") .stream()
2. 强制使用HTTP/1.1协议
若远程服务器启用HTTP/2,可能存在帧缓冲导致流式失效,可强制切换到HTTP/1.1:
import play.api.libs.ws.HttpVersion val futureResponse = ws.url(imageUrl) .withMethod("GET") .withHttpVersion(HttpVersion.HTTP_1_1) .stream()
3. 手动设置分块传输响应头
确认远程服务器返回的响应是否包含Transfer-Encoding: chunked头,若未返回,需在本地响应中手动添加:
futureResponse.map { response => Ok.chunked(response.bodyAsSource) .withHeaders( "Transfer-Encoding" -> "chunked", "Content-Type" -> response.headers.get("Content-Type").flatMap(_.headOption).getOrElse("application/octet-stream") ) }
4. 调整Play配置禁用内部缓冲
在application.conf中修改WS客户端参数,关闭响应缓冲:
play.ws.client.responseBufferSize = 0 play.ws.compressionEnabled = false
内容的提问来源于stack exchange,提问作者mohit
相关产品推荐
相关产品推荐

