java servlet通过HTTP连接提供文件

时间:2010-10-20 16:24:00

标签: java servlets file-io

我有以下代码(服务器是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 并且不提供该文件。

任何线索? 谢谢 A.K。

3 个答案:

答案 0 :(得分:3)

你不能保证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;
}

答案 1 :(得分:1)

避免这些类型的问题是我从Commons IO开始的原因。如果这是一个选项,您的代码将如下所示。

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

无需重新发明轮子。

答案 2 :(得分:0)

.read()调用返回的字节数可能少于您请求的字节数。这意味着您需要使用.read()的te returnvalue作为.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;
    }