简体   繁体   中英

java servlet serving a file over HTTP connection

I have the following code(Server is Tomcat/Linux).

// Send the local file over the current HTTP connection

  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; } 

With some files of type 3gp When i attach the debugger, in line:

outStream.write(buffer, 0, readBlockSize);

it breaks out the while with the following error; ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line:299 And the file is not served.

Any clues? Thanks AK

You can't guarantee that InputStream.read(byte[], int, int) will actually read the desired number of bytes: it may read less. Even your call to available() will not provide that guarantee. You should use the return value from fin.read to find out how many bytes were actually read and only write that many to the output.

I would guess that the problem you see could be related to this. If the block read is less than the available size then your buffer will be partially filled and that will cause problems when you write too many bytes to the output.

Also, don't allocate a new array every time through the loop! That will result in a huge number of needless memory allocations that will slow your code down, and will potentially cause an OutOfMemoryError if available() returns a large number.

Try this:

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;
}

Avoiding these types of problems is why I start with Commons IO. If that's an option, your code would be as follows.

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

No need reinventing the wheel.

It is possible that the .read() call returns less bytes than you requested. This means you need to use te returnvalue of .read() as argument to the .write() call:

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

apart from this, it is better to pre-allocate a buffer and use it (your could could try to use a 2Gb buffer if your file is large :-))

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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