を、ここからダウンロードリモートファイルをストリーミングし、それらをストリーミングするために許可する簡単なCORSプロキシの実装ですクライアントに送信します。 メモリ内のすべてのファイルを読み込みません。
import play.api.libs.iteratee._
private def getAndForwardStream(requestHolder: WSRequestHolder)(computeHeaders: ResponseHeaders => ResponseHeader): Future[SimpleResult] = {
val resultPromise = scala.concurrent.Promise[SimpleResult]
requestHolder.get { wsResponseHeaders: ResponseHeaders =>
val (wsResponseIteratee, wsResponseEnumerator) = Concurrent.joined[Array[Byte]]
val result = SimpleResult(
header = computeHeaders(wsResponseHeaders),
body = wsResponseEnumerator
)
resultPromise.success(result)
wsResponseIteratee
}
resultPromise.future
}
def corsProxy(url: URL) = Action.async { implicit request =>
val requestHolder = WS.url(url.toString).withRequestTimeout(10000)
getAndForwardStream(requestHolder) { wsResponseHeaders: ResponseHeaders =>
// We use the WS response headers and transmit them unchanged to the client, except we add the CORS header...
val originToAllow = request.headers.get("Origin").getOrElse("*")
val headers = wsResponseHeaders.headers.mapValues(_.head) + ("Access-Control-Allow-Origin" -> originToAllow)
ResponseHeader(
status = wsResponseHeaders.status,
headers = headers
)
}
}
ここで重要な部分は、play.api.libs.iteratee.Concurrent.joined[Array[Byte]]
の使用です。 Iteratee/Enumeratorのペアを作成して、Iterateeにバイトを追加するたびに、これらのバイトが列挙子によって列挙されるようにします。あなたはWS応答を消費するIterateeを必要
- :ので
これが欠けていました。
- 再生フレームワークの応答を生成するには、列挙子が必要です。
ありがとう、 'f.ahcResponse.getResponseBodyAsBytes'の両方のソリューションはバイナリデータでも動作します。ストリーミング機能は私が思ったよりも簡単だと思われます:-) – Sonson123
これはブロックしませんか? InputStreamsは通常は.... –
実際には読み込み時にブロックされませんが、メモリ内に読み込まれているためです。これを避けるには、消費関数の引数をとる 'get()'のオーバーロードされた形式を使用する必要があります: 'get [A](consumer:(ResponseHeaders)⇒Iteratee [Array [Byte]、A])' –