所以我用Java从头开始创建了自己的个人HTTP服务器。到目前为止,它运行良好,但有一个主要缺陷。当我尝试将大文件传递到浏览器时,会出现Java堆空间错误。我知道如何通过JVM修复这个错误,但我正在寻找长期的解决方案。
//declare an integer for the byte length of the file
int length = (int) f.length();
//start the fileinput stream.
FileInputStream fis = new FileInputStream(f);
//byte array with the length of the file
byte[] bytes = new byte[length];
//write the file until the bytes is empty.
while ((length = fis.read(bytes)) != -1 ){
write(bytes, 0, length);
}
flush();
//close the file input stream
fis.close();
这种方式成功地将文件发送到浏览器,并且完美地对其进行流式传输但问题是,因为我正在创建一个具有文件长度的字节数组。当文件很大时,我会得到堆空间错误。
我已经通过使用如下所示的缓冲区消除了这个问题,并且我不再出现堆空间错误但是下面显示的方式无法正确地在浏览器中传输文件。这就好像文件字节正在被打乱,并一起被发送到浏览器。
final int bufferSize = 4096;
byte buffer[] = new byte[bufferSize];
FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis);
while ( true )
{
int length = bis.read( buffer, 0, bufferSize );
if ( length < 0 ) break;
write( buffer, 0, length );
}
flush();
bis.close();
fis.close();
注1:
所有正确的响应标头都被完美地发送到浏览器。
注2:
这两种方式在计算机浏览器上都能完美地工作,但只有第一种能手机浏览器上工作(但有时会给我带来堆空间错误)。如果有人知道如何正确地将文件发送到浏览器并正确地流式传输,我将是一个非常非常高兴的人
提前感谢!:)
从BufferedInputStream
读取时,可以允许其缓冲区处理缓冲,没有理由将所有内容都读取到byte[]
(当然也不是整个文件的byte[]
)。一次读取一个byte
,并依赖于流的内部缓冲区。类似
FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis);
int abyte;
while ((abyte = bis.read()) != -1 ){
write(abyte);
}
Emm。。。正如我所看到的,无论如何,你都会尝试在代码中使用块,正如我所记得的,即使是apacheHttpClient+FileUpload解决方案也有大约<2.1GB或其他(如果我错了,请纠正我)所以这有点难。。。
我还没有尝试过这个解决方案,但作为一个测试,你可以在客户端和服务器上使用java.ioRandomAccessFile与File(Input/Output)Stream相结合,而不是一次读写整个文件,而是一系列的,比如<例如30MB块,以避免恼人的内存外错误;可以在此处找到使用RandomAccessFile的示例https://examples.javacodegeeks.com/core-java/io/randomaccessfile/java-randomaccessfile-example/
但你给出的细节仍然较少:(我的意思是,你的客户端是否应该是一个常见的Java应用程序?
如果你有一些额外的信息,请让我知道
祝你好运:)