最近在整合和上传下载相关的工具类,做了个小demo,如图
点击 download链接,程序自动下载使用outputStream write 一个那片海.mp4,这个mp4 大概 44.76MB
代码如下:
private int i = 0; @RequestMapping("/download") public void download(HttpServletRequest request,HttpServletResponse response) throws IOException{ i++; log.info("access i:{}", i); String pathname = null; pathname = "D:\\Downloads\\那片海.mp4"; pathname = "C:\\Users\\feilong\\Downloads\\那片海.mp4"; //pathname = "D:\\Downloads\\viewfile.png"; //pathname = "D:\\Downloads\\export-飞天奔月.opml"; //int contentLength = inputStream.available(); File file = new File(pathname); int contentLength = (int) FileUtil.getFileSize(file); // 以流的形式下载文件。 InputStream inputStream = new FileInputStream(pathname); String saveFileName = FileUtil.getFileName(pathname); download(saveFileName, inputStream, contentLength, request, response); }
普通的IE浏览器下载,不会出现问题,但是如果是迅雷下载,或者是 360极速浏览器开了 “使用迅雷下载加速模块”功能
日志里面瞬间就会出现 10个相同的请求
17:59:45 INFO (DownloadController.java:74) download() - access i:7 17:59:45 INFO (DownloadController.java:74) download() - access i:8 17:59:45 INFO (DownloadController.java:74) download() - access i:9 17:59:45 DEBUG (Browser.java:85) <init>() - the user-agent:[Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36] 17:59:45 INFO (DownloadController.java:74) download() - access i:10 17:59:45 INFO (DownloadController.java:122) download() - begin download~~,saveFileName:[那片海.mp4],contentLength:[44.76MB] 17:59:45 DEBUG (AbstractHandlerExceptionResolver.java:132) resolveException() - Resolving exception from handler [public void com.feilong.controller.DownloadController.download(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException]: ClientAbortException: java.net.SocketException: Connection reset by peer: socket write error 17:59:45 DEBUG (AbstractHandlerExceptionResolver.java:132) resolveException() - Resolving exception from handler [public void com.feilong.controller.DownloadController.download(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException]: ClientAbortException: java.net.SocketException: Software caused connection abort: socket write error 17:59:45 INFO (DownloadController.java:122) download() - begin download~~,saveFileName:[那片海.mp4],contentLength:[44.76MB] 17:59:45 INFO (DownloadController.java:122) download() - begin download~~,saveFileName:[那片海.mp4],contentLength:[44.76MB] 17:59:45 INFO (DownloadController.java:122) download() - begin download~~,saveFileName:[那片海.mp4],contentLength:[44.76MB] 17:59:45 INFO (DownloadController.java:122) download() - begin download~~,saveFileName:[那片海.mp4],contentLength:[44.76MB] 17:59:45 INFO (DownloadController.java:74) download() - access i:11
并且 log中会报 异常
17:59:45 DEBUG (FrameworkServlet.java:976) processRequest() - Could not complete request org.apache.catalina.connector.ClientAbortException: null at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:413) ~[tomcat-embed-core-7.0.47.jar:7.0.47] at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:480) ~[tomcat-embed-core-7.0.47.jar:7.0.47] at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:359) ~[tomcat-embed-core-7.0.47.jar:7.0.47] at org.apache.catalina.connector.OutputBuffer.close(OutputBuffer.java:309) ~[tomcat-embed-core-7.0.47.jar:7.0.47] at org.apache.catalina.connector.CoyoteOutputStream.close(CoyoteOutputStream.java:108) ~[tomcat-embed-core-7.0.47.jar:7.0.47] at com.feilong.commons.core.io.IOWriteUtil.write(IOWriteUtil.java:154) ~[feilong-core-1.0.8-SNAPSHOT.jar:1.0.8-SNAPSHOT] at com.feilong.commons.core.io.IOWriteUtil.write(IOWriteUtil.java:97) ~[feilong-core-1.0.8-SNAPSHOT.jar:1.0.8-SNAPSHOT] at com.feilong.controller.DownloadController.download(DownloadController.java:147) ~[DownloadController.class:na] at com.feilong.controller.DownloadController.download(DownloadController.java:92) ~[DownloadController.class:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_11]
Caused by: java.net.SocketException: Connection reset by peer: socket write error at java.net.SocketOutputStream.socketWrite0(Native Method) ~[na:1.8.0_11] at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109) ~[na:1.8.0_11] at java.net.SocketOutputStream.write(SocketOutputStream.java:153) ~[na:1.8.0_11] at org.apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.java:215) ~[tomcat-embed-core-7.0.47.jar:7.0.47] at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:480) ~[tomcat-embed-core-7.0.47.jar:7.0.47] at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:366) ~[tomcat-embed-core-7.0.47.jar:7.0.47] at org.apache.coyote.http11.InternalOutputBuffer$OutputStreamOutputBuffer.doWrite(InternalOutputBuffer.java:240) ~[tomcat-embed-core-7.0.47.jar:7.0.47] at org.apache.coyote.http11.filters.IdentityOutputFilter.doWrite(IdentityOutputFilter.java:84) ~[tomcat-embed-core-7.0.47.jar:7.0.47] at org.apache.coyote.http11.AbstractOutputBuffer.doWrite(AbstractOutputBuffer.java:192) ~[tomcat-embed-core-7.0.47.jar:7.0.47] at org.apache.coyote.Response.doWrite(Response.java:517) ~[tomcat-embed-core-7.0.47.jar:7.0.47] at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:408) ~[tomcat-embed-core-7.0.47.jar:7.0.47] ... 52 common frames omitted
究其原因:
/* * 在写数据的时候, 对于 ClientAbortException 之类的异常, 是因为客户端取消了下载,而服务器端继续向浏览器写入数据时, 抛出这个异常,这个是正常的。 * 尤其是对于迅雷这种吸血的客户端软件, 明明已经有一个线程在读取 * 如果短时间内没有读取完毕,迅雷会再启第二个、第三个。。。线程来读取相同的字节段, * 直到有一个线程读取完毕,迅雷会 KILL掉其他正在下载同一字节段的线程, 强行中止字节读出,造成服务器抛 ClientAbortException。 */
这对项目是不小的一笔开销 (从日志中可以看到,每个相同的请求 都会过 下 Interceptor)
对于这种异常,我们可以在代码中忽略掉,避免 log太多了,代码示例如下:
try{ OutputStream outputStream = response.getOutputStream(); //这种 如果文件一大,很容易内存溢出 //inputStream.read(buffer); //outputStream = new BufferedOutputStream(response.getOutputStream()); //outputStream.write(buffer); IOWriteUtil.write(inputStream, outputStream); if (log.isInfoEnabled()){ Date endDate = new Date(); log.info( "end download,saveFileName:[{}],contentLength:[{}],time use:[{}]", saveFileName, FileUtil.formatSize(contentLength), DateExtensionUtil.getIntervalForView(beginDate, endDate)); } }catch (IOException e){ //ClientAbortException: java.net.SocketException: Connection reset by peer: socket write error final String exceptionName = e.getClass().getName(); if (StringUtil.isContain(exceptionName, "ClientAbortException") || StringUtil.isContain(e.getMessage(), "ClientAbortException")){ log.warn( "[ClientAbortException],maybe user use Thunder soft or abort client soft download,exceptionName:[{}],exception message:[{}] ,request User-Agent:[{}]", exceptionName, e.getMessage(), RequestUtil.getHeaderUserAgent(request)); }else{ log.error("[download exception],exception name: " + exceptionName, e); throw e; } }
网站是时候禁用迅雷下载了
相关推荐
问题1:TOMCAT下载文件出错:org.apache.catalina.connector.ClientAbortException. 问题2:TOMCAT记录接收数据大小、发送数据大小和请求处理时间
21:23:44,676 WARN StreamResult:45 - StreamResultX Warn : socket write error 如果出现该警告说明正确执行,该警告说明,Socket非正常中断,但是流确实已经关闭,自此再也不用看到上面出现的讨厌异常结果。 ...
java-poi-excel-导出20万条记录
### POI学习笔记知识点解析 #### 一、POI简介 Apache POI是一个开源的Java API,用于处理Microsoft Office格式的文件,包括Excel (.xls, .xlsx), PowerPoint (.ppt, .pptx) 和 Word (.doc, .docx)。...
根据提供的信息,我们可以总结出... error: function(xhr, status, error) { // 处理错误情况 } }); ``` 以上是根据提供的信息整理的Java相关知识点。希望这些内容能够帮助你更好地理解和掌握Java及其相关技术。
3. **错误信息**:后台抛出`ClientAbortException`异常,提示为`IOException:null`。 4. **特殊行为**:手机默认浏览器在请求视频时,会同时向后台发送两个请求。 针对这些问题,我们首先排除了一些常见的原因,...
- **ClientAbortException**:当客户端中断连接时可能会抛出`ClientAbortException`。这通常是由于网络问题或客户端操作导致的。 #### 4. 其他注意事项 - 在实际开发中,建议使用Apache Commons IO库中的`IOUtils....
在我们做struts2文件下载的时候,经常会遇到这种问题:点“打开/保存”一切正常,但当我们点击“取消”时,却报一堆的异常(其中包括ClientAbortException异常),附件中使用struts2-sunspoter-stream-1.0.jar插件可...
在我们做struts2文件下载的时候,经常会遇到这种问题:点“打开/保存”一切正常,但当我们点击“取消”时,却报一堆的异常(其中包括ClientAbortException异常),非常让人头疼,如何彻底解决呢?附件中使用struts2-...