【问题标题】:JAVA: Stream any file to browser correctlyJAVA:将任何文件正确流式传输到浏览器
【发布时间】:2016-04-01 16:02:24
【问题描述】:

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

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

提前感谢您! :)

【问题讨论】:

  • 您似乎没有发送Content-Length 标头,我也没有看到Content-Type。标头对 HTTP 相当重要。
  • 哦,我忘了把它添加到我的问题中。响应标头已正确发送!
  • 我可以对您的代码风格和一些细节提出质疑,但是从浏览器的角度来看,第二个版本的行为应该与第一个相同。更具体地说明您的意思,“就好像文件字节正在被打乱并一起发送到浏览器。”这对故障排除没有帮助。
  • 您使用什么write() 方法来写入数据?也许这个错误就在那里,并且只有在重复调用时才会出现。
  • 您不应该将整个文件读入缓冲区以进行流式传输,通过缓冲您应该一次读取和写入一个字节(并让缓冲区处理它)。

标签: java file stream server


【解决方案1】:

BufferedInputStream 读取时,您可以允许其缓冲区处理缓冲,没有理由将所有内容读入byte[](当然不是整个文件的byte[])。一次读取一个byte,并依赖流的内部缓冲区。比如,

FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis);
int abyte;
while ((abyte = bis.read()) != -1 ){
    write(abyte);
}

【讨论】:

  • 这实际上使它工作 Elliott,非常感谢你 :)
【解决方案2】:

Emm...正如我所看到的,无论如何您都尝试在代码中使用块, 我记得,即使是 apache HttpClient+FileUpload 解决方案的文件大小限制约为 (如果我错了,请纠正我)所以这有点困难...... p>

我还没有尝试过该解决方案,但作为测试,您可以将java.io.RandomAccessFile 与客户端和服务器上的 File(Input/Output)Stream 结合使用,而不是一次读取和写入整个文件,而是按顺序读取和写入例如,可以说 https://examples.javacodegeeks.com/core-java/io/randomaccessfile/java-randomaccessfile-example/

但是您仍然提供的细节较少:(我的意思是您的客户端是否应该是一个普通的 Java 应用程序?


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

祝你好运:)

【讨论】:

    猜你喜欢
    • 2010-10-11
    • 2016-08-02
    • 2013-04-18
    • 2010-09-14
    • 2010-12-21
    • 2012-02-17
    • 2015-06-08
    • 1970-01-01
    • 2015-04-21
    相关资源
    最近更新 更多