尝试获取大型附件时出现异常

时间:2012-12-20 12:21:24

标签: java mailing

我正在使用saaj来获取我的java servlet附件(使用apache和tomcat托管)。

尝试调用message.getAttachments();时(消息是SOAPMessage对象):

  • 如果附件很小(几KB) - 它可以正常工作

  • 如果附件很大(几MB) - 它会抛出以下异常:

     java.lang.RuntimeException: org.jvnet.mimepull.MIMEParsingException: java.io.IOException: The system cannot find the path specified
        at com.sun.xml.messaging.saaj.soap.MessageImpl.getAttachments(MessageImpl.java:826)
        at MyCode.MyServlet.doPost(MyServlet.java:215)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
        at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190)
        at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:283)
        at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:767)
        at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:697)
        at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:889)
        at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
        at java.lang.Thread.run(Unknown Source)
    Caused by: org.jvnet.mimepull.MIMEParsingException: java.io.IOException: The system cannot find the path specified
        at org.jvnet.mimepull.MemoryData.createNext(MemoryData.java:93)
        at org.jvnet.mimepull.Chunk.createNext(Chunk.java:59)
        at org.jvnet.mimepull.DataHead.addBody(DataHead.java:82)
        at org.jvnet.mimepull.MIMEPart.addBody(MIMEPart.java:192)
        at org.jvnet.mimepull.MIMEMessage.makeProgress(MIMEMessage.java:235)
        at org.jvnet.mimepull.MIMEMessage.parseAll(MIMEMessage.java:176)
        at org.jvnet.mimepull.MIMEMessage.getAttachments(MIMEMessage.java:101)
        at com.sun.xml.messaging.saaj.packaging.mime.internet.MimePullMultipart.parseAll(MimePullMultipart.java:118)
        at com.sun.xml.messaging.saaj.packaging.mime.internet.MimePullMultipart.parse(MimePullMultipart.java:129)
        at com.sun.xml.messaging.saaj.packaging.mime.internet.MimeMultipart.getCount(MimeMultipart.java:199)
        at com.sun.xml.messaging.saaj.soap.MessageImpl.initializeAllAttachments(MessageImpl.java:1384)
        at com.sun.xml.messaging.saaj.soap.MessageImpl.getAttachments(MessageImpl.java:824)
        ... 22 more
    Caused by: java.io.IOException: The system cannot find the path specified
        at java.io.WinNTFileSystem.createFileExclusively(Native Method)
        at java.io.File.createTempFile(Unknown Source)
        at java.io.File.createTempFile(Unknown Source)
        at org.jvnet.mimepull.MemoryData.createNext(MemoryData.java:87)
        ... 33 more
    

我该如何解决这个问题?

谢谢!

2 个答案:

答案 0 :(得分:1)

产生异常的MimePull的源代码说明了这一点:

if (!config.isOnlyMemory() && dataHead.inMemory >= config.memoryThreshold) {
         try {
             String prefix = config.getTempFilePrefix();
             String suffix = config.getTempFileSuffix();
             File dir = config.getTempDir();
             File tempFile = (dir == null)
                     ? File.createTempFile(prefix, suffix) // here your code crashes
                     : File.createTempFile(prefix, suffix, dir);
             LOGGER.fine("Created temp file = "+tempFile);
             dataHead.dataFile = new DataFile(tempFile);
         } catch(IOException ioe) {
             throw new MIMEParsingException(ioe);
         }

它尝试打开临时文件,因为传递了内存大小阈值 它被称为

at MyCode.MyServlet.doPost(MyServlet.java:215)

看起来您正在使用SAAJ接收消息并启用了MimePull插件(使用-Dsaaj.use.mimepull=true标志)。它应该允许接收更大的文件,因为MimePull实现使用临时文件作为后备。

现在坏消息似乎是,您无法通过SAAJ配置配置MimePull阅读器。 好消息是您可以通过系统属性File.createTempFile(...)调整java.io.tmpdir的逻辑。

尝试从-Djava.io.tmpdir=/path/to/tmpdir开始。

否则可能会尝试直接使用MimePull来消息,我自己从未这样做过,所以不要问我这个问题。 ; - )

修改:
或者,如果您不希望附件吸收所有内存,请通过设置-Dsaaj.use.mimepull=false完全关闭MimePull。

答案 1 :(得分:0)

我们通过将Jersey-Libs版本从1.13更改为1.19来解决问题。似乎1.13是错误的。