[英]How to send a InputStream in play framework in an java only project without chunked responses?
In a Java (only) Play 2.3 project we need to send a non-chunked response of an InputStream
directly to the client. 在Java(仅)Play 2.3项目中,我们需要直接向客户端发送
InputStream
的非分块响应。 The InputStream
comes from a remote service from which we want to stream directly to the client, without blocking or buffering to a local file. InputStream
来自远程服务,我们希望从该服务直接将其流传输到客户端,而不会阻塞或缓冲到本地文件。 Since we know the size before reading the input stream, we do not want a chunked response. 因为我们在读取输入流之前就知道了大小,所以我们不需要分块的响应。
What is the best way to return a result for an input stream with a known size? 对于已知大小的输入流,返回结果的最佳方法是什么? (preferable without using Scala).
(最好不使用Scala)。
When looking at the default ok(file, ..)
method for returning File objects it goes deep into play internals which are only accessible from scala, and it uses the play-internal execution context which can't even be accessed from outside. 当查看默认的
ok(file, ..)
方法以返回File对象时,它会进入只能从scala访问的播放内部,并且使用甚至无法从外部访问的内部播放执行上下文。 Would be nice if it would work identical, just with an InputStream
. 如果它可以与
InputStream
一样工作,那就太好了。
FWIW I have now found a way to serve an InputStream, which basically duplicates the logic which the Results.ok(File)
method to allow directly passing in an InputStream
. FWIW,我现在找到了一种服务InputStream的方法,该方法基本上重复了
Results.ok(File)
方法允许直接传递到InputStream
的逻辑。
The key is to use the scala call to create an Enumerator from an InputStream: play.api.libs.iteratee.Enumerator$.MODULE$.fromStream
关键是使用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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.