【问题标题】:File not found exception for temporary files临时文件未找到文件异常
【发布时间】:2013-08-27 15:39:35
【问题描述】:

我正在构建 Java 应用程序(Spring & JSF & PrimeFaces)。我将文件上传到服务器,但是,如果我在文件上传结束后立即单击“下一步”按钮,我会收到此错误:

Aug 24, 2013 8:12:34 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/codekata] threw exception [Request processing failed; nested exception is org.springframework.webflow.execution.repository.FlowExecutionRestorationFailureException: A problem occurred restoring the flow execution with key 'e1s3'] with root cause
java.io.FileNotFoundException: C:\Users\Luke\AppData\Local\Temp\upload__6f71235a_140b1bdd246__8000_00000011.tmp (The system cannot find the file specified)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at org.apache.commons.fileupload.disk.DiskFileItem.readObject(DiskFileItem.java:709)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1004)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1891)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796)
     java.lang.Thread.run(Thread.java:722)

如果我等待几秒钟,一切正常。 我假设上传文件需要有时间将自己复制到临时文件夹中,有没有人知道如何解决这个问题。我使用的是 Tomcat 7。

这是我的下载方法:

public StreamedContent getDownloadFile()
    {
        InputStream inputStream = new ByteArrayInputStream(selectedBook.getBookText().getText().getBytes());
        return new DefaultStreamedContent(inputStream, "text/plain", selectedBook.getTitle() + ".txt", BookBean.encoding);
    }

谢谢, 卢克。

【问题讨论】:

    标签: java spring jsf tomcat primefaces


    【解决方案1】:

    根据堆栈跟踪,您似乎将UploadedFile 实例存储为一个类的属性,该类本身就是Serializable。这个不对。您应该在&lt;p:fileUpload handleFileUpload&gt; 文件上传侦听器方法中立即 获取上传的文件内容(或者如果您使用&lt;p:fileUpload mode="simple"&gt;,请点击提交按钮)。将其存放在更永久的位置。例如。本地磁盘文件系统或数据库,甚至可能作为byte[] bean 属性。然后传递本地磁盘文件系统文件名,或数据库PK,或byte[],以便有一个句柄来下载文件。

    总结一下,只要确保您的 Serializable 支持 bean 完全没有 UploadedFile 属性,这个问题就会消失。

    【讨论】:

    • 您是否建议将上传的文件放入@SessionScoped bean Controller?同样从上面的代码中您可以看到文件是从传递给它的文本创建的,它不是 Serializable bean 的成员,尽管该方法是在 Serializable bean 中实现的。在上传的情况下,UploadedFile 是 Serializable bean 的成员是对的。另请参阅我对上一个答案的上述评论。
    • 在幕后,UploadedFile 实例存储在内存和/或临时存储位置。它不是上传文件内容的永久可重用挂钩。您有责任尽快获取其内容并将其存储在更永久的位置。反过来,您可以安全地将其文件名存储为String,或将其 DB PK 存储为Number,或将其内容存储为byte[] 在会话范围的 bean 中。这些东西是可序列化的。
    • 我明白了,我将实施更改并稍后返回结果。
    【解决方案2】:

    如果没有任何代码,首先想到的是同步线程,这样您的按钮操作将等待上传过程完成。

    编辑:从您描述的方式来看,您的操作显然被调用得太早了,因此该文件尚未正确写入。

    解决此问题的一种方法是检查文件是否存在:

    File file = new File(<path_to_tmp_file>);
      if(file.exists()){
        //Download file
      }
    

    【讨论】:

    • 但是文件上传完成了,至少在用户界面上,当文件上传完成时,“下一步”按钮被启用。如果我不等待几秒钟,我按下一步并得到上面给出的错误。因为 next 后面的逻辑使用文件。
    • 也许你可以暂时把你的文件作为一个对象保存在某个地方,特别是如果你立即阅读它,你可以将它作为参数传递。可以肯定的是,如果您将此文件存储在数据库中,您会遇到更少的问题,但我想它不符合您的要求。那就是说你的文件存储在哪里?我猜是在应用程序文件之外的某个地方?
    • 用户上传文件(文本文件),我阅读了文本。然后我从给定的文本中生成一些新文本,接下来我用新文本创建一个文件,然后用户下载该文件。该文件是在用户下载它之前立即创建的,因此我假设没有太多时间从创建点复制到 temp。
    • 您是否尝试将我的答案添加到您的代码中?它可能有帮助,也可能没有,但在您这样做之前我们无法确定。
    • 是的,他通常知道一些东西:P
    猜你喜欢
    • 2021-03-22
    • 1970-01-01
    • 2019-03-29
    • 2019-06-26
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多