【问题标题】:Exception when trying to get large attachments尝试获取大型附件时出现异常
【发布时间】:2012-12-20 12:21:24
【问题描述】:

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

当尝试调用message.getAttachments();(其中 message 是 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
    

我该如何解决这个问题?

谢谢!

【问题讨论】:

  • 根据异常找不到大文件,你确定文件存在并且路径正确吗?
  • 我认为该实现使用临时文件来处理大型附件。我认为它试图将其写入一个不存在的位置。我只是不知道它在哪里。附件来自网络(带肥皂)

标签: java mailing


【解决方案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 阅读器。 好消息可能是您可以通过系统属性java.io.tmpdir 调整File.createTempFile(...) 的逻辑。

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

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

编辑:
或者,如果您不希望附件占用您的所有内存,则通过设置 -Dsaaj.use.mimepull=false 完全关闭 MimePull。

【讨论】:

    【解决方案2】:

    我们通过将 Jersey-Libs 版本从 1.13 更改为 1.19 解决了这个问题。看来 1.13 有问题。

    【讨论】:

      猜你喜欢
      • 2018-10-09
      • 2011-09-17
      • 1970-01-01
      • 1970-01-01
      • 2021-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-21
      相关资源
      最近更新 更多