Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用servlet下载大型文件_Java_Servlets_File Io - Fatal编程技术网

Java 使用servlet下载大型文件

Java 使用servlet下载大型文件,java,servlets,file-io,Java,Servlets,File Io,我正在使用ApacheTomcatServer6和Java1.6,并试图将大型mp3文件写入ServletOutputStream,供用户下载。目前,文件大小在50-750MB之间 较小的文件不会造成太多问题,但对于较大的文件,它会导致套接字异常损坏管道 File fileMp3 = new File(objDownloadSong.getStrSongFolder() + "/" + strSongIdName); FileInputStream fis = new FileInputStre

我正在使用ApacheTomcatServer6和Java1.6,并试图将大型mp3文件写入ServletOutputStream,供用户下载。目前,文件大小在50-750MB之间

较小的文件不会造成太多问题,但对于较大的文件,它会导致套接字异常损坏管道

File fileMp3 = new File(objDownloadSong.getStrSongFolder() + "/" + strSongIdName);
FileInputStream fis = new FileInputStream(fileMp3);
response.setContentType("audio/mpeg");
response.setHeader("Content-Disposition", "attachment; filename=\"" + strSongName + ".mp3\";");
response.setContentLength((int) fileMp3.length());
OutputStream os = response.getOutputStream();

try {
    int byteRead = 0;
    while ((byteRead = fis.read()) != -1) {
        os.write(byteRead);
    }
    os.flush();
} catch (Exception excp) {
    downloadComplete = "-1";
    excp.printStackTrace();
} finally {
    os.close();
    fis.close();
}
但是对于较大的文件,它似乎正在写入堆中,这会导致OutOfMemory错误并导致整个服务器停机

原因不在给定的代码片段中。原因之一是将整个文件读入
字节[]
,但在您发布的代码中似乎没有这种情况。另外,Tomcat6默认情况下每2KB自动刷新一次响应流。今后,请将整个stacktrace也包括在问题中。它可能表示链中的
HttpServletResponseWrapper
和/或
过滤器
,该过滤器可能缓冲整个响应

也得到插座异常断管

File fileMp3 = new File(objDownloadSong.getStrSongFolder() + "/" + strSongIdName);
FileInputStream fis = new FileInputStream(fileMp3);
response.setContentType("audio/mpeg");
response.setHeader("Content-Disposition", "attachment; filename=\"" + strSongName + ".mp3\";");
response.setContentLength((int) fileMp3.length());
OutputStream os = response.getOutputStream();

try {
    int byteRead = 0;
    while ((byteRead = fis.read()) != -1) {
        os.write(byteRead);
    }
    os.flush();
} catch (Exception excp) {
    downloadComplete = "-1";
    excp.printStackTrace();
} finally {
    os.close();
    fis.close();
}
这只意味着另一方已经中止了请求。从服务器端来说,这没有什么可反对的,从技术上讲,这也不会造成伤害。你可以放心地忽略它

但是对于较大的文件,它似乎正在写入堆中,这会导致OutOfMemory错误并导致整个服务器停机

原因不在给定的代码片段中。原因之一是将整个文件读入
字节[]
,但在您发布的代码中似乎没有这种情况。另外,Tomcat6默认情况下每2KB自动刷新一次响应流。今后,请将整个stacktrace也包括在问题中。它可能表示链中的
HttpServletResponseWrapper
和/或
过滤器
,该过滤器可能缓冲整个响应

也得到插座异常断管

File fileMp3 = new File(objDownloadSong.getStrSongFolder() + "/" + strSongIdName);
FileInputStream fis = new FileInputStream(fileMp3);
response.setContentType("audio/mpeg");
response.setHeader("Content-Disposition", "attachment; filename=\"" + strSongName + ".mp3\";");
response.setContentLength((int) fileMp3.length());
OutputStream os = response.getOutputStream();

try {
    int byteRead = 0;
    while ((byteRead = fis.read()) != -1) {
        os.write(byteRead);
    }
    os.flush();
} catch (Exception excp) {
    downloadComplete = "-1";
    excp.printStackTrace();
} finally {
    os.close();
    fis.close();
}

这只意味着另一方已经中止了请求。从服务器端来说,这没有什么可反对的,从技术上讲,这也不会造成伤害。您可以放心地忽略它。

您正在写入的文件是3/4s的gig,一次一个字节

尝试使用更大的缓冲区

int BUFF_SIZE = 1024;
byte[] buffer = new byte[BUFF_SIZE];
File fileMp3 = new File(objDownloadSong.getStrSongFolder() + "/" + strSongIdName);
FileInputStream fis = new FileInputStream(fileMp3);
response.setContentType("audio/mpeg");
response.setHeader("Content-Disposition", "attachment; filename=\"" + strSongName + ".mp3\";");
response.setContentLength((int) fileMp3.length());
OutputStream os = response.getOutputStream();
int byteCount = 0;
try {
    do {
        byteCount = fis.read(buffer);
        if (byteCount == -1)
           break;
        os.write(buffer, 0, byteCount);
        os.flush();
    } while (true);
}
} catch (Exception excp) {
    downloadComplete = "-1";
    excp.printStackTrace();
} finally {
    os.close();
    fis.close();
}

顺便说一句,在我开始回答这个问题之前,我启动了一个空循环,将循环75000000000次(您的大文件大小),看看需要多长时间。它仍在运行。

您每次写入的文件是3/4千兆字节的文件吗

尝试使用更大的缓冲区

int BUFF_SIZE = 1024;
byte[] buffer = new byte[BUFF_SIZE];
File fileMp3 = new File(objDownloadSong.getStrSongFolder() + "/" + strSongIdName);
FileInputStream fis = new FileInputStream(fileMp3);
response.setContentType("audio/mpeg");
response.setHeader("Content-Disposition", "attachment; filename=\"" + strSongName + ".mp3\";");
response.setContentLength((int) fileMp3.length());
OutputStream os = response.getOutputStream();
int byteCount = 0;
try {
    do {
        byteCount = fis.read(buffer);
        if (byteCount == -1)
           break;
        os.write(buffer, 0, byteCount);
        os.flush();
    } while (true);
}
} catch (Exception excp) {
    downloadComplete = "-1";
    excp.printStackTrace();
} finally {
    os.close();
    fis.close();
}

顺便说一句,在我开始回答这个问题之前,我启动了一个空循环,将循环75000000000次(您的大文件大小),看看需要多长时间。它仍在运行。

下载大文件的一个常见问题是,您正在缓冲整个文件,如果客户端没有足够的耐心,可能会导致管道破裂。当文件太大时,服务器上的内存也可能不足

尝试通过这样做来强制分块编码

response.setContentLength(-1);

这将导致连接器逐块传输文件。

下载大文件的一个常见问题是您正在缓冲整个文件,如果客户端没有足够的耐心,这可能会导致管道破裂。当文件太大时,服务器上的内存也可能不足

尝试通过这样做来强制分块编码

response.setContentLength(-1);

这将导致连接器逐块流式传输文件。

重复的?@scompt:无法回答此特定问题。您的客户端代码是什么样子的?重复的?@scompt:无法回答此特定问题。您的客户端代码是什么样子的?谢谢大家,但我的主要问题是,我无法在客户端下载文件,并且没有收到任何响应错误。我想下载大文件,比如说abt 10 mb。是的,我理解。你明白我的答案吗?你注意到关于stacktrace的部分了吗?你想让我显示整个异常。是的,我注意到了,如果我丢失了sumthing,请告诉我否。谢谢Balus,但我的主要问题是我无法在客户端下载文件,并且没有响应错误。我想下载大文件,比如说abt 10 mb。是的,我理解这一点。你明白我的答案吗?你注意到stacktrace的部分了吗?你想让我显示整个异常。是的,我注意到了,如果我缺少sumthing,请告诉我否。对不起,我看不出更大的缓冲区如何解决这个问题。它只会使它更快,消耗(一点)更多的内存。
OutOfMemoryError
当然不能由OP使用的1字节“缓冲区”引起。管道中断错误意味着另一方(客户端)已中止连接/请求/下载本身,这与服务器端代码无关。抱歉,我看不出更大的缓冲区如何解决此问题。它只会使它更快,消耗(一点)更多的内存。
OutOfMemoryError
当然不能由OP使用的1字节“缓冲区”引起。管道中断错误意味着另一端(客户端)已中止连接/请求/下载本身,这与服务器端代码无关。默认情况下,Tomcat缓冲区不超过2K,并自动刷新响应。所以我怀疑这是否是根本原因。顺便说一下,也可以通过省略整个
setContentLength()
调用来触发分块编码。默认情况下,Tomcat缓冲区不超过2K,并自动刷新响应。所以我怀疑这是否是根本原因。顺便说一下,也可以通过省略整个
setContentLength()
调用来触发分块编码。