2013-08-24 103 views
4

我正在構建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); 
    } 

感謝, 盧克。

回答

8

基於堆棧跟蹤,它看起來就像是要存儲的UploadedFile實例作爲一個類的屬性,該屬性本身就是Serializable。這個不對。你應該抓取上傳的文件內容立即<p:fileUpload handleFileUpload>文件上傳監聽器方法(或提交按鈕,如果你使用<p:fileUpload mode="simple">)。將它存放在更加永久的位置。例如。本地磁盤文件系統或數據庫,或者甚至可以作爲bean屬性。然後傳遞本地磁盤文件系統文件名或數據庫PK或byte[],以便有一個句柄將文件下載回來。

總結,只要確保您的Serializable支持豆完全沒有UploadedFile財產,並且此問題將消失。

+0

您是否建議將上傳的文件放入@SessionScoped bean控制器?同樣從上面的代碼中,你可以看到文件是從傳遞給它的文本創建的,它不是Serializable bean的成員,儘管該方法是在Serializable bean中實現的。在上傳的情況下,你是正確的,UploadedFile是Serializable bean的成員。另請參閱我對上一個答案的上述評論。 – Lukasz

+1

在封面下方,'UploadedFile'實例存儲在內存和/或臨時存儲位置。這不是上傳文件內容的永久性可重複使用鉤子。您有責任儘快獲取內容**,並將其存儲在更加永久的位置。您可以反過來安全地將其文件名存儲爲'String',或將其數據庫PK存儲爲'Number',或將其內容存儲爲會話作用域bean中的byte []'。那些東西是可序列化的。 – BalusC

+0

我明白了,我會實施這些改變,並在以後得到結果。 – Lukasz

1

沒有任何代碼,首先想到的是同步線程,以便您的按鈕操作將等待上傳過程完成。

編輯:從您描述它的方式來看,您的操作顯然被稱爲過早,以至於該文件尚未正確書寫。要解決這個問題

的一種方法是,以檢查文件是否存在:

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

但文件上傳完成後,至少在用戶界面上,文件上傳完成後,啓用「下一步」按鈕。如果我不等幾秒鐘,我會按next並獲得上面給出的錯誤。因爲後面的邏輯使用該文件。 – Lukasz

+0

也許你可以暫時保留某個地方作爲你的文件的對象,特別是如果你立即讀它,你可以將它作爲參數傳遞給它。最關鍵的是,如果你將這個文件存儲在數據庫中,你會遇到更少的問題,但我想它不符合你的要求。那說明你的文件存儲在哪裏?應用程序文件之外的某處,我猜? – sam

+0

用戶上傳文件(文本文件),我看了文字。然後我從給定的文本中產生一些新的文本,然後我用新文本創建一個文件,然後用戶下載文件。該文件在用戶下載之前立即創建,因此我沒有太多時間假設從創建的點複製到臨時文件。 – Lukasz