所以我从头开始用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();
NOTE1:
所有正确的响应标头正在完美地发送到浏览器。
注2:
两种方式在计算机浏览器上完全,但只有第一种方式适用于智能手机的浏览器(但有时它会给我堆空间错误)。 如果有人知道如何正确地将文件发送到浏览器并正确地传输它们,我将是一个非常非常快乐的人。
提前谢谢! :)
答案 0 :(得分:2)
从BufferedInputStream
读取时,您可以允许其缓冲区处理缓冲,因此没有理由将所有内容都读入byte[]
(当然不是整个byte[]
文件)。一次读一个byte
,并依赖流的内部缓冲区。像,
FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis);
int abyte;
while ((abyte = bis.read()) != -1 ){
write(abyte);
}
答案 1 :(得分:0)
嗯......正如我所看到的,无论如何你试图在代码中使用块, 我记得,即使apache HttpClient+FileUpload解决方案的文件大小限制大约为&lt; = 2.1GB或某些(如果我错了,请纠正我)所以这有点难...
我还没有尝试过该解决方案,但作为测试,您可以在客户端和服务器上使用java.io.RandomAccessFile与文件(输入/输出)流结合使用,而不是在整个文件中读取和写入整个文件。例如,为了避免令人讨厌的外部存储错误,可以说&lt; = 30MB块。可以在此处找到使用RandomAccessFile的示例https://examples.javacodegeeks.com/core-java/io/randomaccessfile/java-randomaccessfile-example/
但是你还是给出了更少的细节:(我的意思是你的客户想要成为一个普通的Java应用程序吗?
如果您有其他信息,请告诉我
祝你好运:)