2010-04-18 39 views
11

我開發了一個Java EE web應用程序。此應用程序允許用戶在瀏覽器的幫助下上傳文件。一旦用戶上傳了他的文件,該應用程序首先將上傳的文件存儲在服務器上(它正在運行),然後對其進行處理。如何通過Java EE Web應用程序將文件存儲在服務器(Web容器)上?

目前,我在服務器上存儲文件,如下所示:

try { 
    // formFile represents the uploaded file 
    FormFile formFile = programForm.getTheFile(); 
    String path = getServlet().getServletContext().getRealPath("") + "/" 
     + formFile.getFileName(); 
    System.out.println(path); 
    file = new File(path); 
    outputStream = new FileOutputStream(file); 
    outputStream.write(formFile.getFileData()); 
} 

何地,formFile表示上傳的文件。現在

,問題是,它是運行良好,在某些服務器上,但在某些服務器上的getServlet().getServletContext().getRealPath("")將返回null讓我得到最終的路徑是null/filename和文件不在服務器上存儲。

當我檢查API爲ServletContext.getRealPath()方法,我發現了以下內容:

public java.lang.String getRealPath(java.lang.String path)

返回包含對於給定的虛擬路徑的實際路徑的字符串。例如,路徑"/index.html"返回服務器文件系統上的絕對文件路徑將由請求"http://host/contextPath/index.html"提供服務,其中contextPath是此ServletContext的上下文路徑。

返回的真實路徑將採用適合運行servlet容器的計算機和操作系統的形式,包括正確的路徑分隔符。如果servlet容器由於某種原因無法將虛擬路徑轉換爲真實路徑(例如,從.war歸檔中使內容可用時),則此方法返回null。

那麼,有沒有用,我可以存儲在返回nullgetServlet().getServletContext().getRealPath("")

回答

13

寫在Java EE容器中的文件系統並不推薦使用,特別是如果你需要處理的數據寫入:

  • 它不是事務
  • 它損害了便攜性(如果你有什麼在集羣環境中)
  • 它需要爲目標位置

如果這是一種選擇,我會存儲在數據庫或u文件設置的外部參數選擇一個JCR存儲庫(如Jackrabbit)。

+0

@Pascal我只想存儲一個文件以便稍後處理。所以我認爲將該文件存儲在數據庫中不是一個好主意?你怎麼看?該文件是一個.csv文件。如果你認爲我應該將它存儲在數據庫中,那麼我應該以字節形式還是以任何其他形式存儲它,因爲文件的大小可以爲100或200 MB。其次,我第一次聽說「Jackrabbit」,我不知道它是什麼。我看着它的網站,但沒有找到任何教程。那麼你能告訴我哪一個更好:使用數據庫還是使用「Jackrabbit」? – 2010-04-20 09:30:13

+1

@Yatendra我是寫入文件系統的「記錄」的潛在缺陷。對於許多應用程序來說,這可能不是一個選項,但對您而言可能不是問題。現在,回答你的問題...... 1)寫入數據庫可以完成(在LOB中);這並不理想,但如果你每天不寫幾千個文件,那應該沒問題。 2)Jackrabbit是JCR API(JSR-170)的一個實現,它是將文件寫入和存儲到內容存儲庫的標準API,因此也是一種替代方案。但是對於一個小應用程序來說,使用JCR存儲庫聽起來有點過分。 *我*會使用數據庫。 – 2010-04-20 16:24:32

+0

我有一個類似的問題,但我需要存儲小文件 - 所以使用任何需要單獨設置和支持的數據庫是一個很大的開銷。因此,對這個答案投下贊成票並投票贊成@Will Hartung的答案 - 因爲它讓我對簡單問題更加簡單。 – Vladimir 2011-05-18 05:49:34

20

通過規範這些服務器還對文件的任何其他方式,保證您唯一的「真正的」路徑獲得形成一個servlet容器是一個臨時目錄。

你可以通過ServletContext.gerAttribute(「javax.servlet.context.tempdir」)來獲得。但是,這些文件在Web上下文中不可見(即,您無法發佈簡單的URL來傳遞這些文件),並且無法保證文件以任何方式在Web應用程序或服務器重新啓動後繼續存在。

如果您只需要一個地方短時間存儲工作文件,那麼這對您來說可以正常工作。

如果您確實需要一個目錄,您可以將它設置爲配置參數(環境變量,Java屬性(即java -Dyour.file.here =/tmp/files ...),上下文參數集在web.xml中,通過Web表單存儲在數據庫中的配置參數等)。然後由部署人員爲您設置此目錄。你可能需要一個特定於容器的機制來將外部目錄「掛載」到你的web應用程序中(Glassfish作爲「備用文檔根」,其他人也有類似的概念) ,否則你將需要編寫一個servlet /過濾器來在你的web應用程序之外提供文件存儲。這FileServlet是相當完整的,正如你所看到的,創建你自己的雖然不難,但做正確的做法並不是微不足道的。

編輯:

的基本精神是一致的,但不是使用 「getRealPath」,簡單地使用 「的getInitParameter」。

所以:

String filePath = getServletContext().getInitParameter("storedFilePath") + "/" + fileName; 

而且用自己的方式。再次

編輯:

對於路徑的內容,我想給它一個絕對路徑。否則,您需要知道應用程序服務器在執行期間將其默認路徑設置爲何處,並且每個應用程序服務器都可能使用不同的目錄。例如,我相信Glassfish的工作目錄是正在運行的域的config目錄。不是一個特別明顯的選擇。

因此,絕對使用絕對路徑。這樣您就知道文件將放到哪裏,並且您可以控制該目錄的操作系統級別的訪問權限(如果有必要的話)。

+0

我需要將文件存儲在可以在服務器和Web應用程序重新啓動後保留的目錄中。從你回答,我想通過設置一個上下文參數使其成爲一個配置參數。但我沒有得到如何存儲文件。你能提供一個例子或對一個例子的參考嗎? – 2010-04-18 18:12:49

+0

@你告訴我如何檢索我已經知道的上下文參數的值。可能是我的意見不清楚。其實,我的意思是你會給「storedFilePath」上下文參數賦予什麼樣的價值。相對文件路徑或絕對文件路徑? – 2010-04-20 13:14:53

+0

如果你給一個相對路徑,你將如何將它轉換爲絕對路徑? – 2010-04-20 13:17:13

相關問題