HttpServletResponseに書き込むInputStreamがあります。このアプローチがあり、byte []の使用のために時間がかかりすぎます。
InputStream is = getInputStream();
int contentLength = getContentLength();
byte[] data = new byte[contentLength];
is.read(data);
//response here is the HttpServletResponse object
response.setContentLength(contentLength);
response.write(data);
速度と効率の面で、それを行う最善の方法は何だろうと思っていました。
最初にJavaのメモリに完全にコピーするのではなく、ブロックに書き込むだけです。以下の基本的な例では、10KBのブロックで書き込みます。この方法では、完全なコンテンツの長さではなく、わずか10 KBの一貫したメモリ使用量になります。また、エンドユーザーはコンテンツの一部をより早く取得し始めます。
response.setContentLength(getContentLength());
byte[] buffer = new byte[10240];
try (
InputStream input = getInputStream();
OutputStream output = response.getOutputStream();
) {
for (int length = 0; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
}
パフォーマンスに関するクレームとして、NIO Channels
と直接割り当てられた ByteBuffer
を使用できます。いくつかのカスタムユーティリティクラスに次のユーティリティ/ヘルパーメソッドを作成します。 Utils
:
public static long stream(InputStream input, OutputStream output) throws IOException {
try (
ReadableByteChannel inputChannel = Channels.newChannel(input);
WritableByteChannel outputChannel = Channels.newChannel(output);
) {
ByteBuffer buffer = ByteBuffer.allocateDirect(10240);
long size = 0;
while (inputChannel.read(buffer) != -1) {
buffer.flip();
size += outputChannel.write(buffer);
buffer.clear();
}
return size;
}
}
次に、次のように使用します。
response.setContentLength(getContentLength());
Utils.stream(getInputStream(), response.getOutputStream());
BufferedInputStream in = null;
BufferedOutputStream out = null;
OutputStream os;
os = new BufferedOutputStream(response.getOutputStream());
in = new BufferedInputStream(new FileInputStream(file));
out = new BufferedOutputStream(os);
byte[] buffer = new byte[1024 * 8];
int j = -1;
while ((j = in.read(buffer)) != -1) {
out.write(buffer, 0, j);
}
これは最善の方法に非常に近いと思いますが、次の変更をお勧めします。固定サイズのバッファ(Say 20K)を使用してから、ループで読み取り/書き込みを実行します。
ループのように
byte[] buffer=new byte[20*1024];
outputStream=response.getOutputStream();
while(true) {
int readSize=is.read(buffer);
if(readSize==-1)
break;
outputStream.write(buffer,0,readSize);
}
ps:あなたのプログラムは常にそのままでは動作しません。なぜなら、読み取りはあなたが与えた配列全体を常に満たすわけではないからです。