使用 Java 从服务器下载大文件时出错

Error in Downloading large files from Server using Java

我是 Java 中文件处理的新手。我写了一个代码,应该从服务器下载一个文件。 该代码适用于大小不超过 70 MB.If 的文件,下载大文件会抛出异常。

SRVE0260E: The server cannot use the error page specified for your application to handle the Original Exception printed below.

Original Exception: Error Message: java.lang.OutOfMemoryError Error Code: 500 Target Servlet: null Error Stack: java.lang.OutOfMemoryError " at app.web.webcontroller.webAction.DownloadCsvAction.execute(DownloadCsvAction.java:49)" " at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:422)" " at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:228)" " at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1164)" " at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:397)" " at javax.servlet.http.HttpServlet.service(HttpServlet.java:718)" " at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)" " at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1530)" " at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1470)" " at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:131)" " at app.systemController.RequestTimerFilter.doFilter_http(RequestTimerFilter.java:73)" " at app.systemController.RequestTimerFilter.doFilter(RequestTimerFilter.java:61)" " at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:188)" " at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:116)" " at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:77)" " at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:858)" " at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:824)" " at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:458)" " at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:175)" " at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:91)" " at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:862)" " at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1583)" " at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:178)" " at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:455)" " at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:384)" " at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:83)" " at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)" " at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)" " at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)" " at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)" " at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)" " at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)" " at com.ibm.io.async.ResultHandler.run(ResultHandler.java:905)" " at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1550)"

Error Page Exception: Error Message: java.lang.IllegalStateException: SRVE0199E: OutputStream already obtained Error Code: 0 Target Servlet: null Error Stack: java.lang.IllegalStateException: SRVE0199E: OutputStream already obtained " at com.ibm.ws.webcontainer.srt.SRTServletResponse.getWriter(SRTServletResponse.java:719)" " at org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:187)" " at org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:175)" " at org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:262)" " at org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:177)" " at org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:137)" " at com.ibm._jsp._Error500._jspService(_Error500.java:177)" " at com.ibm.ws.jsp.runtime.HttpJspBase.service(HttpJspBase.java:98)" " at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)" " at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1530)" " at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1470)" " at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:104)" " at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:77)" " at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:858)" " at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:824)" " at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:458)" " at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:175)" " at com.ibm.wsspi.webcontainer.servlet.GenericServletWrapper.handleRequest(GenericServletWrapper.java:121)" " at com.ibm.ws.jsp.webcontainerext.AbstractJSPExtensionServletWrapper.handleRequest(AbstractJSPExtensionServletWrapper.java:239)" " at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.forward(WebAppRequestDispatcher.java:330)" " at com.ibm.ws.webcontainer.webapp.WebApp.sendError(WebApp.java:3209)" " at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:987)" " at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:458)" " at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:175)" " at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:91)" " at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:862)" " at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1583)" " at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:178)" " at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:455)" " at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:384)" " at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:83)" " at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)" " at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)" " at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)" " at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)" " at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)" " at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)" " at com.ibm.io.async.ResultHandler.run(ResultHandler.java:905)" " at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1550)"

此异常打印在下载的文件中,而不是原始数据中。

response.setHeader("Content-Disposition","attachment;filename=\""+fileName+"\"");
        response.setContentType("application/octet-stream");
         File downloadFile = new File(fileUrl\fileName);
         OutputStream out = response.getOutputStream();
         FileInputStream in = new FileInputStream(downloadFile); 
         int size=(int)downloadFile.length()+1;
         byte[] buffer = new byte[size];
         int length;
         while ((length = in.read(buffer)) != -1){
            out.write(buffer, 0, length);
         }
         in.close();
         out.flush();

同样在代码片段中,请告诉我是否有任何方法可以优化我的代码以使其更快。

您创建了一个大小与您要传输的文件相同的缓冲区。对于大文件,您将得到发生的事情:OutOfMemoryError,因为您的堆上没有足够的 space 来容纳那么多数据。

最简单的解决方法是选择较小的缓冲区大小,例如 64k。这应该不会显着降低性能:

byte[] buffer = new byte[64 * 1024];

此代码终止您的应用程序:

int size=(int)downloadFile.length()+1;
byte[] buffer = new byte[size];

因为您使用了太大的缓冲区所以 JVM 将 OutOfMemory。您应该将文件分成小块,例如 byte[] buffer = new byte[1024]