文件的上傳與下載

要將表單頁面的method屬性設(shè)置為post方式
   enctype屬性設(shè)置為multipart/form-dat
<form action="${pageContext.request.contextPath}/servlet/UploadHandleServlet" 
      enctype="multipart/form-data" method="post">
         上傳用戶:<input type="text" name="username"><br/>
         上傳文件1:<input type="file" name="file1"><br/>
         上傳文件2:<input type="file" name="file2"><br/>
         <input type="submit" value="提交">
  </form>
一般選擇采用apache的開源工具common-fileupload這個(gè)文件上傳組件
使用FileUpload組件時(shí)需要導(dǎo)入common-fileupload是依賴于common-io兩個(gè)jar包

文件上傳的相關(guān)API

FileItem接口
用于封裝單個(gè)表單字段元素的數(shù)據(jù)一個(gè)表單字段元素對(duì)應(yīng)一個(gè)FileItem對(duì)象
FileItem的實(shí)現(xiàn)類實(shí)現(xiàn)了Serializable接口,支持序列化操作

1.  booleanisFormField()
       isFormField方法用于判斷FileItem類對(duì)象封裝的數(shù)據(jù)是一個(gè)普通文本表單字段,還是一個(gè)文件表單字段,如果是普通表單字段則返回true,否則返回false。因此,可以使用該方法判斷是否為普通表單域,還是文件上傳表單域。
2.  String getName()
       getName方法用于獲得文件上傳字段中的文件名。
      注意IE或FireFox中獲取的文件名是不一樣的,IE中是絕對(duì)路徑,F(xiàn)ireFox中只是文件名。
3.  StringgetFieldName()
      getFieldName方法用于返回表單標(biāo)簽name屬性的值。如上例中<input type="text" name="column" />的value。
4.  void write(Filefile)
       write方法用于將FileItem對(duì)象中保存的主體內(nèi)容保存到某個(gè)指定的文件中。如果FileItem對(duì)象中的主體內(nèi)容是保存在某個(gè)臨時(shí)文件中,該方法順利完成后,臨時(shí)文件有可能會(huì)被清除。該方法也可將普通表單字段內(nèi)容寫入到一個(gè)文件中,但它主要用途是將上傳的文件內(nèi)容保存在本地文件系統(tǒng)中。
5.  StringgetString()
      getString方法用于將FileItem對(duì)象中保存的數(shù)據(jù)流內(nèi)容以一個(gè)字符串返回,它有兩個(gè)重載的定義形式:
     publicjava.lang.String getString()
     public java.lang.String getString(java.lang.String encoding)
            throws java.io.UnsupportedEncodingException
       前者使用缺省的字符集編碼將主體內(nèi)容轉(zhuǎn)換成字符串,后者使用參數(shù)指定的字符集編碼將主體內(nèi)容轉(zhuǎn)換成字符串。如果在讀取普通表單字段元素的內(nèi)容時(shí)出現(xiàn)了中文亂碼現(xiàn)象,請調(diào)用第二個(gè)getString方法,并為之傳遞正確的字符集編碼名稱。
6.  StringgetContentType()
        getContentType 方法用于獲得上傳文件的類型,即表單字段元素描述頭屬性“Content-Type”的值,如“image/jpeg”。如果FileItem類對(duì)象對(duì)應(yīng)的是普通表單字段,該方法將返回null。
7.  booleanisInMemory()
        isInMemory方法用來判斷FileItem對(duì)象封裝的數(shù)據(jù)內(nèi)容是存儲(chǔ)在內(nèi)存中,還是存儲(chǔ)在臨時(shí)文件中,如果存儲(chǔ)在內(nèi)存中則返回true,否則返回false。
8.  void delete()
       delete方法用來清空FileItem類對(duì)象中存放的主體內(nèi)容,如果主體內(nèi)容被保存在臨時(shí)文件中,delete方法將刪除該臨時(shí)文件。
       盡管當(dāng)FileItem對(duì)象被垃圾收集器收集時(shí)會(huì)自動(dòng)清除臨時(shí)文件,但及時(shí)調(diào)用delete方法可以更早的清除臨時(shí)文件,釋放系統(tǒng)存儲(chǔ)資源。另外,當(dāng)系統(tǒng)出現(xiàn)異常時(shí),仍有可能造成有的臨時(shí)文件被永久保存在了硬盤中。
9.  InputStreamgetInputStream()
    以流的形式返回上傳文件的數(shù)據(jù)內(nèi)容。
10. long getSize()
      返回該上傳文件的大?。ㄒ宰止?jié)為單位)

DiskFileItemFactory類

將請求消息實(shí)體中的每一個(gè)項(xiàng)目封裝成單獨(dú)的DiskFileItem (FileItem接口的實(shí)現(xiàn)) 對(duì)象的任務(wù)
由 org.apache.commons.fileupload.FileItemFactory 接口的默認(rèn)實(shí)現(xiàn) 
org.apache.commons.fileupload.disk.DiskFileItemFactory 來完成。當(dāng)上傳的文件項(xiàng)目比較小時(shí),直接保存在內(nèi)存中(速度比較快),比較大時(shí),以臨時(shí)文件的形式,保存在磁盤臨時(shí)文件夾(雖然速度慢些,但是內(nèi)存資源是有限的)。
屬性
1) public static final int DEFAULT_SIZE_THRESHOLD :將文件保存在內(nèi)存還是磁盤臨時(shí)文件夾的默認(rèn)臨界值,值為10240,即10kb。
2) private File repository:用于配置在創(chuàng)建文件項(xiàng)目時(shí),當(dāng)文件項(xiàng)目大于臨界值時(shí)使用的臨時(shí)文件夾,默認(rèn)采用系統(tǒng)默認(rèn)的臨時(shí)文件路徑,可以通過系統(tǒng)屬性 java.io.tmpdir獲取。如下代碼:
System.getProperty("java.io.tmpdir");
3) private int sizeThreshold:用于保存將文件保存在內(nèi)存還是磁盤臨時(shí)文件夾的臨界值
構(gòu)造方法
1) public DiskFileItemFactory()
      采用默認(rèn)臨界值和系統(tǒng)臨時(shí)文件夾構(gòu)造文件項(xiàng)工廠對(duì)象。
2) public DiskFileItemFactory(int sizeThreshold,File repository)
      采用參數(shù)指定臨界值和系統(tǒng)臨時(shí)文件夾構(gòu)造文件項(xiàng)工廠對(duì)象。
3) FileItem createItem() 
       根據(jù)DiskFileItemFactory相關(guān)配置將每一個(gè)請求消息實(shí)體項(xiàng)目創(chuàng)建成DiskFileItem 實(shí)例,并返回。該方法從來不需要我們親自調(diào)用,F(xiàn)ileUpload組件在解析請求時(shí)內(nèi)部使用。
4) void setSizeThreshold(int sizeThreshold)
        Apache文件上傳組件在解析上傳數(shù)據(jù)中的每個(gè)字段內(nèi)容時(shí),需要臨時(shí)保存解析出的數(shù)據(jù),以便在后面進(jìn)行數(shù)據(jù)的進(jìn)一步處理(保存在磁盤特定位置或插入數(shù)據(jù)庫)。因?yàn)镴ava虛擬機(jī)默認(rèn)可以使用的內(nèi)存空間是有限的,超出限制時(shí)將會(huì)拋出“java.lang.OutOfMemoryError”錯(cuò)誤。如果上傳的文件很大,例如800M的文件,在內(nèi)存中將無法臨時(shí)保存該文件內(nèi)容,Apache文件上傳組件轉(zhuǎn)而采用臨時(shí)文件來保存這些數(shù)據(jù);但如果上傳的文件很小,例如600個(gè)字節(jié)的文件,顯然將其直接保存在內(nèi)存中性能會(huì)更加好些。
        setSizeThreshold方法用于設(shè)置是否將上傳文件已臨時(shí)文件的形式保存在磁盤的臨界值(以字節(jié)為單位的int值),如果從沒有調(diào)用該方法設(shè)置此臨界值,將會(huì)采用系統(tǒng)默認(rèn)值10KB。對(duì)應(yīng)的getSizeThreshold() 方法用來獲取此臨界值。
5) void setRepository(File repository)
        setRepositoryPath方法用于設(shè)置當(dāng)上傳文件尺寸大于setSizeThreshold方法設(shè)置的臨界值時(shí),將文件以臨時(shí)文件形式保存在磁盤上的存放目錄。有一個(gè)對(duì)應(yīng)的獲得臨時(shí)文件夾的 File getRespository() 方法。
         注意:當(dāng)從沒有調(diào)用此方法設(shè)置臨時(shí)文件存儲(chǔ)目錄時(shí),默認(rèn)采用系統(tǒng)默認(rèn)的臨時(shí)文件路徑,可以通過系統(tǒng)屬性 java.io.tmpdir 獲取。如下代碼:
System.getProperty("java.io.tmpdir");
Tomcat系統(tǒng)默認(rèn)臨時(shí)目錄為“<tomcat安裝目錄>/temp/”

ServletFileUpload

構(gòu)造方法:
1) public ServletFileUpload()

     構(gòu)造一個(gè)未初始化的實(shí)例,需要在解析請求之前先調(diào)用setFileItemFactory()方法設(shè)置 fileItemFactory屬性。

2) public ServletFileUpload(FileItemFactory fileItemFactory)

     構(gòu)造一個(gè)實(shí)例,并根據(jù)參數(shù)指定的FileItemFactory 對(duì)象,設(shè)置 fileItemFactory屬性。

ServletFileUpload類常用方法:
1)  public void setSizeMax(long sizeMax)
        setSizeMax方法繼承自FileUploadBase類,用于設(shè)置請求消息實(shí)體內(nèi)容(即所有上傳數(shù)據(jù))的最大尺寸限制,以防止客戶端惡意上傳超大文件來浪費(fèi)服務(wù)器端的存儲(chǔ)空間。其參數(shù)是以字節(jié)為單位的long型數(shù)字。

       在請求解析的過程中,如果請求消息體內(nèi)容的大小超過了setSizeMax方法的設(shè)置值,將會(huì)拋出FileUploadBase內(nèi)部定義的SizeLimitExceededException異常(FileUploadException的子類)。該方法有一個(gè)對(duì)應(yīng)的讀方法:public long getSizeMax()方法。

2) public void setFileSizeMax(long fileSizeMax)
        setFileSizeMax方法繼承自FileUploadBase類,用于設(shè)置單個(gè)上傳文件的最大尺寸限制,以防止客戶端惡意上傳超大文件來浪費(fèi)服務(wù)器端的存儲(chǔ)空間。其參數(shù)是以字節(jié)為單位的long型數(shù)字。該方法有一個(gè)對(duì)應(yīng)的讀方法:public long geFileSizeMax()方法。

       在請求解析的過程中,如果單個(gè)上傳文件的大小超過了setFileSizeMax方法的設(shè)置值,將會(huì)拋出FileUploadBase內(nèi)部定義的FileSizeLimitExceededException異常(FileUploadException的子類)。

3) public List parseRequest(javax.servlet.http.HttpServletRequest req)
        parseRequest 方法是ServletFileUpload類的重要方法,它是對(duì)HTTP請求消息體內(nèi)容進(jìn)行解析的入口方法。它解析出FORM表單中的每個(gè)字段的數(shù)據(jù),并將它們分別包裝成獨(dú)立的FileItem對(duì)象,然后將這些FileItem對(duì)象加入進(jìn)一個(gè)List類型的集合對(duì)象中返回。

       該方法拋出FileUploadException異常來處理諸如文件尺寸過大、請求消息中的實(shí)體內(nèi)容的類型不是“multipart/form-data”、IO異常、請求消息體長度信息丟失等各種異常。每一種異常都是FileUploadException的一個(gè)子類型。

4)  public FileItemIterator getItemIterator(HttpServletRequest request)
        getItemIterator方法和parseRequest 方法基本相同。但是getItemIterator方法返回的是一個(gè)迭代器,該迭代器中保存的不是FileItem對(duì)象,而是FileItemStream 對(duì)象,如果你希望進(jìn)一步提高新能,你可以采用getItemIterator方法,直接獲得每一個(gè)文件項(xiàng)的數(shù)據(jù)輸入流,做底層處理;如果性能不是問題,你希望代碼簡單,則采用parseRequest方法即可。

5) public stiatc boolean isMultipartContent(HttpServletRequest req)
        isMultipartContent方法方法用于判斷請求消息中的內(nèi)容是否是“multipart/form-data”類型,是則返回true,否則返回false。isMultipartContent方法是一個(gè)靜態(tài)方法,不用創(chuàng)建ServletFileUpload類的實(shí)例對(duì)象即可被調(diào)用。

6) getFileItemFactory()和setFileItemFactory(FileItemFactory)
       方法繼承自FileUpload類,用于設(shè)置和讀取fileItemFactory屬性。

7) public void setProgressListener(ProgressListener pListener)
      設(shè)置文件上傳進(jìn)度監(jiān)聽器。該方法有一個(gè)對(duì)應(yīng)的讀取方法:ProgressListener getProgressListener()。

8) public void setHeaderEncoding()
       在文件上傳請求的消息體中,除了普通表單域的值是文本內(nèi)容以外,文件上傳字段中的文件路徑名也是文本,在內(nèi)存中保存的是它們的某種字符集編碼的字節(jié)數(shù)組,Apache文件上傳組件在讀取這些內(nèi)容時(shí),必須知道它們所采用的字符集編碼,才能將它們轉(zhuǎn)換成正確的字符文本返回。

        setHeaderEncoding方法繼承自FileUploadBase類,用于設(shè)置上面提到的字符編碼。如果沒有設(shè)置,則對(duì)應(yīng)的讀方法getHeaderEncoding()方法返回null,將采用HttpServletRequest設(shè)置的字符編碼,如果HttpServletRequest的字符編碼也為null,則采用系統(tǒng)默認(rèn)字符編碼??梢酝ㄟ^一下語句獲得系統(tǒng)默認(rèn)字符編碼:

         System.getProperty("file.encoding"));

DiskFileItemFactory

public void setRepository(File repository):設(shè)置臨時(shí)文件的存放目錄

public void setSizeThreshold(int sizeThreshold):設(shè)置緩存的大小

專題:關(guān)于臨時(shí)文件

文件上傳時(shí),自己用IO流處理,一定要在流關(guān)閉后刪除臨時(shí)文件。FileItem.delete()

建議使用:FileItem.writer(File f).會(huì)自動(dòng)刪除臨時(shí)文件。

3.2亂碼問題


a、普通字段的亂碼

FileItem.getString(String charset);編碼要和客戶端一致。

b、上傳的中文文件名亂碼

解決辦法:request.setCharacterEncoding("UTF-8");編碼要和客戶端一致。

3.3文件重名問題

解決辦法:a.txt 多次上傳會(huì)被覆蓋

UUID_a.txt

3.4保證服務(wù)器的安全

把存放文件的目錄,放到用戶直接訪問不到的地方。

3.6限制上傳文件的大小,并給出友好提示

web方式下不適合傳輸較大的文件。

ServletFileUpload.setSizeMax(610241024);//多文件上傳時(shí)總大小限制

3.7限制上傳文件的類型

擴(kuò)展名+文件的MIME類型:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容