InputStreamのサイズを取得する方法は?
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());
入力ストリームのサイズなどはありません。決して終了しないプログラム、または送信を停止しないソケットピアについて考えてみます。そして、それをHttpResponse
ヘッダーに書き込むことを知る必要はありません。 Content-length
は自動的に管理されます。
本当にコンテンツの長さのヘッダーを設定したい場合は、応答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());
注:このアプローチでは、ストリーム全体をメモリに読み込んだため、使用可能なメモリに影響を与え、拡張性が低下する可能性があります。
これを試して
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());
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
について考える必要はありません。
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 ..");
}