我有以下代码(服务器是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。
答案 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;
}