調查一個 pdf 打印報錯:
ExceptionConverter: org.apache.catalina.connector.ClientAbortException: java.net.SocketException: Software caused connection abort: socket write error at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:407) at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:480) at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:366) at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:432) at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:420) at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:91) at java.io.BufferedOutputStream.write(Unknown Source) at com.itextpdf.text.pdf.OutputStreamCounter.write(OutputStreamCounter.java:157) at java.io.ByteArrayOutputStream.writeTo(Unknown Source) at com.itextpdf.text.pdf.PdfStream.toPdf(PdfStream.java:353) at com.itextpdf.text.pdf.PdfIndirectObject.writeTo(PdfIndirectObject.java:157) at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:396) at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:376) at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:329) at com.itextpdf.text.pdf.PdfWriter.addToBody(PdfWriter.java:780) at com.itextpdf.text.pdf.TrueTypeFontUnicode.writeFont(TrueTypeFontUnicode.java:385) at com.itextpdf.text.pdf.FontDetails.writeFont(FontDetails.java:274) at com.itextpdf.text.pdf.PdfWriter.addSharedObjectsToBody(PdfWriter.java:1249) at com.itextpdf.text.pdf.PdfWriter.close(PdfWriter.java:1169) at com.itextpdf.text.pdf.PdfDocument.close(PdfDocument.java:780) at com.itextpdf.text.Document.close(Document.java:409)
可以看到 在 調用 pdf 的 Document.close() 方法時,拋出了上訴錯誤。
調試之後的原因是,在chrome浏覽器中頁面上 點擊一次 打印,打印 servlet 會執行兩次,第一次 可以正常打印,document.close() 可以正常執行,沒有報錯,可以執行完了之後,servlet又一次執行了!所以在第二次 document.close() 時,報錯:
ClientAbortException: java.net.SocketException: Software caused connection abort: socket write error
原因是,浏覽器已經關閉了連接,所以第二次 向浏覽器輸出 :
response.setContentType("application/pdf");
時,才報錯。
發現只有 chrome才存在這個問題。調查的結果:
-----------------------------------------------------------------------------------------
http://blog.lifw.org/post/66162597
貼下全文:
博主在寫一篇關於文件下載的博文 http://blog.lifw.org/post/24251622 時,遇到了一個很惡心的問題,現象是我在 chrome 以及 Safari 浏覽器地址欄直接輸入文件下載鏈接 localhost:8080/download 時,我的 download 方法被請求了兩次,並且第一次拋出如下的 ClientAbortException 異常
然後 chrome 了很多資料,最後終於找到原因:由於 chrome、Safari 等浏覽器為了使網頁加載更快,使用了一種叫做預提取資源,以便更快速地加載網頁機制,也就是說當你在浏覽器中輸入 url 後,即便你還沒回車發送請求,浏覽器也會預先發送請求加載資源,因此每當我在地址欄中輸入 url localhost:8080/download 時,浏覽器便發送請求到我的 download 方法中,然後我的 download 方法給浏覽器返回一個文件下載響應,此時,浏覽器一看是文件下載,不能預先加載,因此便主動關閉了鏈接,便導致了ClientAbortException 異常,然後我回車真正發送了該請求,浏覽器便會下載文件,此時沒有異常,文件下載成功。綜上所訴,便導致 chrome 一個請求發送兩次的現象。
網上查找資料的過程中,看到有的人在做計數統計的時候,如果使用 chrome,則每次請求會計數兩次,其實也是該問題導致的,因此如果你在開發的過程中,如果莫名其妙的遇到一個請求發送多次的問題,不妨往這方面考慮一下,關閉 chrome 的預提取資源功能測試一下,往往便能解決問題。這個問題非常惡心,並且不易察覺,希望本文能對後來人有所幫助。