我从InputStream
获得了ProcessBuilder
,可以实际读取stdout
信息流。
问题:如何知道该内存InputStream
的大小,以便将其写入HttpResponse
http标头?
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
OutputStream out = response.getOutputStream();
int bytes;
while ((bytes = br.read()) != -1) {
out.write(bytes);
}
//how can I know the size of the inmemory stream/file written?
//response.setContentLength((int) pdfFile.length());
答案 0 :(得分:4)
没有输入流的大小。考虑一个永不退出的程序,或者一个永不停止发送的套接字对等体。而且您无需知道将其写入HttpResponse
标头。 Content-length
会自动为您管理。
答案 1 :(得分:2)
如果你真的想设置内容长度标题,你需要在写入响应OutputStream之前读取整个流
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int count;
while ((count = in.read(bytes)) > 0) {
out.write(bytes, 0, count);
}
response.setContentLength(out.size();
out.writeTo(response.getOutputStream());
注意:使用这种方法,您现在已将整个流读入内存,这将对可用内存产生影响,并且可能无法很好地扩展。
答案 2 :(得分:2)
试试这个
InputStream is = process.getInputStream();
ByteArrayOutputStream os = new ByteArrayOutputStream();
int b;
while ((b = is.read()) != -1)
os.write(b);
response.setContentLength(os.size());
response.getOutputStream().write(os.toByteArray());
答案 3 :(得分:1)
InputStream
本身并没有大小。可以想象,它永远可以继续提供字节。或者生产端可以在没有警告的情况下结束流。
如果你必须找出长度,那么你必须读到最后,计算字节数,并在完成时报告长度。
您对HTTP的Content-length
标题感到担忧,而且您已经明白了。事实是,HTTP的原始版本不是为大型动态生成的内容而设计的。协议固有地希望您在开始编写内容之前知道内容的大小 - 但如果它(例如)正在进行的聊天或摄像机的输出,那该怎么可能?
解决方案是HTTP' chunked transfer encoding
。在这里,您不需要设置Content-Length
标头。您设置Transfer-Encoding: chunked
,然后将内容写为块,每个块都有一个大小标题。
HTTP RFC有一个详细信息,或https://en.wikipedia.org/wiki/Chunked_transfer_encoding稍微友好。
但是,大多数HTTP API会向您隐藏此详细信息。除非您从头开始创建Web库(可能是出于学术原因),否则您不必考虑Content-Length
或Transfer-Encoding
。
答案 4 :(得分:0)
import org.apache.commons.io.IOUtils;
byte[] bytes = IOUtils.toByteArray(inputStream);
log.message("bytes .lenght "+bytes.length);
if (bytes.length > 400000)
//some byte range limit`enter code can add any byte range
{
throw new Exception("File Size is larger than 40 MB ..");
}