JAVA:正确地将任何文件流式传输到浏览器

时间:2016-04-01 16:02:24

标签: java file stream server

所以我从头开始用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:

两种方式在计算机浏览器上完全,但只有第一种方式适用于智能手机的浏览器(但有时它会给我堆空间错误)。 如果有人知道如何正确地将文件发送到浏览器并正确地传输它们,我将是一个非常非常快乐的人。

提前谢谢! :)

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应用程序吗?

如果您有其他信息,请告诉我

祝你好运:)