我正在尝试实现一个用于流式传输大型对象的servlet:
oracle.sql.BLOB blob = rs.getBLOB('obj');
InputStream in = blob.getBinaryStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
ServletOutputStream out = response.getOutputStream();
int counter=0
while((length=in.read(buffer)) != -1){
out.write(buffer,0,length);
counter++;
if(counter % 10 == 0){
counter=0;
response.flushBuffer();
}
此代码假设通过chunck将数据发送到客户端块。现在发生的事情是,当我流式传输大型对象(100 MB)时,内存会上升,如果有多个并行下载/流,服务器有时会死掉。
为什么这个flushBuffer()
没有向客户端发送数据?只有在响应关闭后,客户端才会弹出打开/保存文件。
答案 0 :(得分:3)
您必须在写入数据之前设置Content-Length
标头,否则服务器将被强制缓冲所有数据,直到关闭流,此时它可以自己计算值,写入标头,以及发送所有数据。一旦获得输出流,在编写任何数据之前,请设置内容长度:
response.setHeader("Content-Length", String.valueOf(blob.length()));
大多数服务器都足够聪明,可以在此时自行刷新缓冲区,因此您甚至可能不需要调用flushBuffer()
- 尽管它没有受到伤害。
答案 1 :(得分:1)
首先,您需要一个servlet
响应的响应头,以便容器可以知道信息可以在多少字节结束后:
response.setHeader("Content-Length", String.valueOf(blob.length()));