You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 21:07:02