繁体   English   中英

Java Servlet通过HTTP连接提供文件

[英]java servlet serving a file over HTTP connection

我有以下代码(服务器是Tomcat / Linux)。

//通过当前的HTTP连接发送本地文件

  FileInputStream fin = new FileInputStream(sendFile); int readBlockSize; int totalBytes=0; while ((readBlockSize=fin.available())>0) { byte[] buffer = new byte[readBlockSize]; fin.read(buffer, 0, readBlockSize); outStream.write(buffer, 0, readBlockSize); totalBytes+=readBlockSize; } 

对于某些类型为3gp的文件,当我附加调试器时,请注意以下几点:

outStream.write(buffer,0,readBlockSize);

它使用以下错误中断一会儿; ApplicationFilterChain.internalDoFilter(ServletRequest,ServletResponse)行:299并且未提供文件。

有什么线索吗? 谢谢AK

您不能保证InputStream.read(byte [],int,int)会实际读取所需的字节数:它可能读取的字节数更少。 即使您对available()的调用也无法提供保证。 您应该使用fin.read的返回值来找出实际读取了多少字节,然后只将其中的多少写入输出。

我想您看到的问题可能与此有关。 如果读取的块小于可用大小,则缓冲区将被部分填充,并且当您向输出写入太多字节时,这将导致问题。

另外,不要每次循环都分配一个新数组! 这将导致大量不必要的内存分配,这会减慢您的代码速度,并且可能在available()返回大量内存时导致OutOfMemoryError。

尝试这个:

int size;
int totalBytes = 0;
byte[] buffer = new byte[BUFFER_SIZE];
while ((size = fin.read(buffer, 0, BUFFER_SIZE)) != -1) {
    outStream.write(buffer, 0, size);
    totalBytes += size;
}

避免这些类型的问题是我从Commons IO开始的原因。 如果可以的话,您的代码如下。

FileInputStream fin = new FileInputStream(sendFile);
int totalBytes = IOUtils.copy(fin, outStream);

无需重新发明轮子。

.read()调用返回的字节数可能少于您请求的字节数。 这意味着您需要使用.read() te .read()作为.write()调用的参数:

        int bytesRead = fin.read(buffer, 0, readBlockSize);
        outStream.write(buffer, 0, bytesRead);

除此之外,最好预先分配一个缓冲区并使用它(如果您的文件很大,您可以尝试使用2Gb缓冲区:-))

byte[] buffer = new byte[4096]; // define a constant for this max length

while ((readBlockSize=fin.available())>0) {                     
    if (4096 < readBlockSize) {
        readBlockSise = 4096;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM