web-dev-qa-db-ja.com

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());
3
membersound

入力ストリームのサイズなどはありません。決して終了しないプログラム、または送信を停止しないソケットピアについて考えてみます。そして、それをHttpResponseヘッダーに書き込むことを知る必要はありません。 Content-lengthは自動的に管理されます。

4
user207421

本当にコンテンツの長さのヘッダーを設定したい場合は、応答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
lance-java

これを試して

    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());
1
saka1029

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について考える必要はありません。

1
slim
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 ..");
              }