如何在没有分块响应的 java 项目中发送播放框架中的 InputStream?
How to send a InputStream in play framework in an java only project without chunked responses?
在 Java(仅)Play 2.3 项目中,我们需要将 InputStream
的非分块响应直接发送到客户端。 InputStream
来自远程服务,我们希望从该远程服务直接流式传输到客户端,而不阻塞或缓冲到本地文件。由于我们在读取输入流之前就知道大小,因此我们不需要分块响应。
return 已知大小的输入流的结果的最佳方法是什么? (最好不使用 Scala)。
当查看 returning File 对象的默认 ok(file, ..)
方法时,它深入到只能从 scala 访问的播放内部,并且它使用播放内部执行上下文,它不能'甚至无法从外部访问。如果它能以相同的方式工作,那就太好了,只是 InputStream
.
FWIW 我现在找到了一种提供 InputStream 的方法,它基本上复制了 Results.ok(File)
方法允许直接传入 InputStream
.
的逻辑
关键是使用 scala 调用从 InputStream 创建枚举器:play.api.libs.iteratee.Enumerator$.MODULE$.fromStream
private final MessageDispatcher fileServeContext = Akka.system().dispatchers().lookup("file-serve-context");
protected void serveInputStream(InputStream inputStream, String fileName, long contentLength) {
response().setHeader(
HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + fileName + "\"");
// Set Content-Type header based on file extension.
scala.Option<String> contentType = MimeTypes.forFileName(fileName);
if (contentType.isDefined()) {
response().setHeader(CONTENT_TYPE, contentType.get());
} else {
response().setHeader(CONTENT_TYPE, ContentType.DEFAULT_BINARY.getMimeType());
}
response().setHeader(CONTENT_LENGTH, Long.toString(contentLength));
return new WrappedScalaResult(new play.api.mvc.Result(
new ResponseHeader(StatusCode.OK, toScalaMap(response().getHeaders())),
// Enumerator.fromStream() will also close the input stream once it is done.
play.api.libs.iteratee.Enumerator$.MODULE$.fromStream(
inputStream,
FILE_SERVE_CHUNK_SIZE,
fileServeContext),
play.api.mvc.HttpConnection.KeepAlive()));
}
/**
* A simple Result which wraps a scala result so we can call it from our java controllers.
*/
private static class WrappedScalaResult implements Result {
private play.api.mvc.Result scalaResult;
public WrappedScalaResult(play.api.mvc.Result scalaResult) {
this.scalaResult = scalaResult;
}
@Override
public play.api.mvc.Result toScala() {
return scalaResult;
}
}
在 Java(仅)Play 2.3 项目中,我们需要将 InputStream
的非分块响应直接发送到客户端。 InputStream
来自远程服务,我们希望从该远程服务直接流式传输到客户端,而不阻塞或缓冲到本地文件。由于我们在读取输入流之前就知道大小,因此我们不需要分块响应。
return 已知大小的输入流的结果的最佳方法是什么? (最好不使用 Scala)。
当查看 returning File 对象的默认 ok(file, ..)
方法时,它深入到只能从 scala 访问的播放内部,并且它使用播放内部执行上下文,它不能'甚至无法从外部访问。如果它能以相同的方式工作,那就太好了,只是 InputStream
.
FWIW 我现在找到了一种提供 InputStream 的方法,它基本上复制了 Results.ok(File)
方法允许直接传入 InputStream
.
关键是使用 scala 调用从 InputStream 创建枚举器:play.api.libs.iteratee.Enumerator$.MODULE$.fromStream
private final MessageDispatcher fileServeContext = Akka.system().dispatchers().lookup("file-serve-context");
protected void serveInputStream(InputStream inputStream, String fileName, long contentLength) {
response().setHeader(
HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + fileName + "\"");
// Set Content-Type header based on file extension.
scala.Option<String> contentType = MimeTypes.forFileName(fileName);
if (contentType.isDefined()) {
response().setHeader(CONTENT_TYPE, contentType.get());
} else {
response().setHeader(CONTENT_TYPE, ContentType.DEFAULT_BINARY.getMimeType());
}
response().setHeader(CONTENT_LENGTH, Long.toString(contentLength));
return new WrappedScalaResult(new play.api.mvc.Result(
new ResponseHeader(StatusCode.OK, toScalaMap(response().getHeaders())),
// Enumerator.fromStream() will also close the input stream once it is done.
play.api.libs.iteratee.Enumerator$.MODULE$.fromStream(
inputStream,
FILE_SERVE_CHUNK_SIZE,
fileServeContext),
play.api.mvc.HttpConnection.KeepAlive()));
}
/**
* A simple Result which wraps a scala result so we can call it from our java controllers.
*/
private static class WrappedScalaResult implements Result {
private play.api.mvc.Result scalaResult;
public WrappedScalaResult(play.api.mvc.Result scalaResult) {
this.scalaResult = scalaResult;
}
@Override
public play.api.mvc.Result toScala() {
return scalaResult;
}
}