6

我正在尝试实现一个用于流式传输大型对象的 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();
    }

此代码假设通过块将数据发送到客户端块。现在发生的事情是,当我流式传输大型对象(100 MB)时,内存会增加,如果有多个并行下载/流,服务器有时会死机。

为什么这flushBuffer()不向客户端发送数据?只有在响应关闭后,客户端才会弹出打开/保存文件。

4

2 回答 2

3

你必须Content-Length在写数据之前设置header,否则服务器被迫缓冲所有数据,直到流关闭,此时它可以自己计算值,写入header,并发送所有数据。一旦你得到输出流,在你写任何数据之前,设置内容长度:

response.setHeader("Content-Length", String.valueOf(blob.length()));

大多数服务器在这一点上都足够聪明,可以自己刷新缓冲区,所以你可能甚至不需要调用flushBuffer()——尽管它没有坏处。

于 2012-05-11T13:48:30.113 回答
1

首先,你需要一个响应的响应头,servlet这样容器才能知道信息在多少字节后才能结束:

response.setHeader("Content-Length", String.valueOf(blob.length()));
于 2012-05-11T14:06:11.587 回答