web專案利用apache的DiskFileItemFactory和ServletFileUpload上傳圖片

王如霜發表於2018-02-02

      最近在做java的web專案時,遇到圖片上傳此功能,我是利用apache提供的第三方jar來實現的


一:首先需要引用以下兩個jar包

web專案利用apache的DiskFileItemFactory和ServletFileUpload上傳圖片

二:<form>表單要設定屬性enctype="multipart/form-data"

<form name="itemForm" target="_self" id="itemForm" method="post" action="servlet/item/FileUploadServlet" enctype="multipart/form-data">
            <input type="hidden" name="itemNo" value="<%=item.getItemNo() %>">
            <div align="center">
                <table width="95%" border="0" cellpadding="0" cellspacing="0">
                    <tr>
                        <td height="26"><div align="right">物料名稱:&bsp;   </div></td>
                        <td><%=item.getItemName() %></td>
                    </tr>
                    <tr>
                        <td height="74"><div align="right">圖片:&nbsp;</div></td>
                        <td><img src="upload/<%=item.getFileName() %>" width="85" height="49">  </td>
                    </tr>
                    <tr>
                        <td width="22%" height="29"><div align="right"><font color="#FF0000">*</font>選擇圖片:&nbsp;</div>
                        </td>
                        <td width="78%"><input name="fileName" type="file" class="text1" size="40" maxlength="40"></td>
                    </tr>
                </table>
                <div align="center">
                    <input name="btn_upload" class="button1" type="submit"
                        id="btn_upload" value="上傳">
                    &nbsp;&nbsp;&nbsp;&nbsp;
                    <input name="btnBack" class="button1" type="button" id="btnBack"
                        value="返回" onClick="history.go(-1)">
                </div>
            </div>
        </form>

為什麼上傳檔案的表單需要設定enctype=”multipart/form-data”
注意:使用enctype="multipart/form-data"時,表單必須是post提交方式
當點選上傳按鈕時,表單就會將檔案內容也提交到HTML請求中了


三:servlet設定

package com.bjpowernode.drp.basedata.web;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.bjpowernode.drp.basedata.manager.ItemManager;
import com.bjpowernode.drp.basedata.manager.ItemManagerImpl;
import com.bjpowernode.drp.util.ApplicationException;

public class FileUploadServlet extends AbstractItemServlet {
    //檔案下載存放路徑
    private File uploadPath;
    //臨時檔案存放路徑
    private File tempPath;

    public void doPost(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        //1.apache的核心API:DiskFileItemFactory 
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //1.1設定記憶體緩衝區大小
        factory.setSizeThreshold(4096);
        //1.2指定臨時檔案目錄
        factory.setRepository(tempPath);
        //2.apache的核心API:ServletFileUpload ,負責處理上傳的檔案資料
        ServletFileUpload upload = new ServletFileUpload(factory);
        //2.1設定檔案上傳總量(所有上傳檔案)的最大值
        upload.setSizeMax(1000000 * 20);
        //2.2設定編碼格式
        upload.setHeaderEncoding("UTF-8");
        try {
            //2.3.解析request物件,獲取傳過來的資料
            List fileItems = upload.parseRequest(req);
            String itemNo = "";
            for (Iterator iter = fileItems.iterator(); iter.hasNext();) {
                //3.apache的核心API:FileItem
                FileItem item = (FileItem) iter.next();     
                //3.1是普通的表單輸入域
                if(item.isFormField()) {
                    //
                    if ("itemNo".equals(item.getFieldName())) {
                        //3.2用於將FileItem物件中儲存的資料流內容以一個字串返回,
                        itemNo = item.getString();
                    }
                }
                //3.1是type=file的輸入域
                if (!item.isFormField()) {
                    //3.2獲取檔名,IE為絕對路徑,Firefox只有檔名
                    String fileName = item.getName();
                    //3.3獲得上傳檔案的大小
                    long size = item.getSize();
                    if ((fileName == null || fileName.equals("")) && size == 0) {
                        continue;
                    }
                    //擷取字串 ,獲得檔名
                    fileName = fileName.substring(fileName.lastIndexOf("\\") + 1, fileName.length());
                    //3.4 將FileItem物件中儲存的主體內容儲存到指定的檔案中
                    item.write(new File(uploadPath, fileName));
                    //呼叫業務邏輯層
                    itemManager.uploadItemImage(itemNo, fileName);
                }
            //重定向
            res.sendRedirect(req.getContextPath() + "/servlet/item/SearchItemServlet");
        } catch (Exception e) {
            e.printStackTrace();
            throw new ApplicationException("上傳失敗!");
        }
    }

    public void init() throws ServletException {
        //檔案存放目錄
        //獲取servlet容器物件,相當於tomacat容器,getRealPath("upload")獲取upload檔案在容器中的實際釋出執行位置
        uploadPath = new File(getServletContext().getRealPath("upload"));   
        //如果目錄不存在
        if (!uploadPath.exists()) {
            //建立目錄
            uploadPath.mkdir();
        }

        //臨時目錄
        tempPath = new File(getServletContext().getRealPath("temp"));
        if (!tempPath.exists()) {
            tempPath.mkdir();
        }
        //顯示呼叫父類的init方法,因為該類繼承了父類,覆蓋了父類的init()方法
        super.init();
    }
}
  1. apache的核心API:DiskFileItemFactory:是建立FileItem 物件的工廠

    • public void setSizeThreshold(int sizeThreshold) :設定記憶體緩衝區的大小,預設值為10K。當上傳檔案大於緩衝區大小時,fileupload元件將使用臨時檔案快取上傳檔案。
    • public void setRepository(Java.io.File repository)
      指定臨時檔案目錄,預設值為System.getProperty(“java.io.tmpdir”).
  2. apache的核心API:ServletFileUpload ,負責處理上傳的檔案資料

    • setSizeMax(long sizeMax) :設定上傳檔案總量的最大值(所有上傳檔案),用於設定請求訊息實體內容(即所有上傳資料)的最大尺寸限制,以防止客戶端惡意上傳超大檔案來浪費伺服器端的儲存空間。其引數是以位元組為單位的long型數字
    • setFileSizeMax(long fileSizeMax) :設定上傳檔案的最大值(單個檔案),用於設定單個上傳檔案的最大尺寸限制,以防止客戶端惡意上傳超大檔案來浪費伺服器端的儲存空間。其引數是以位元組為單位的long型數字
    • setHeaderEncoding(java.lang.String encoding) :設定編碼格式。在檔案上傳請求的訊息體中,除了普通表單域的值是文字內容以外,檔案上傳欄位中的檔案路徑名也是文字,在記憶體中儲存的是它們的某種字符集編碼的位元組陣列,Apache檔案上傳元件在讀取這些內容時,必須知道它們所採用的字符集編碼,才能將它們轉換成正確的字元文字返回。
    • List parseRequest(HttpServletRequest request):解析request物件,並把表單中的每一個輸入項包裝成一個fileItem 物件,並返回一個儲存了所有FileItem的list集合(form提交採用multipart/form-data,無法採用req.getParameter()取得資料)
    • boolean isMultipartContent(HttpServletRequest request) :判斷上傳表單是否為multipart/form-data型別

    3. apache的核心API:FileItem:是個介面,用來阻止所有的檔案,通過這個統一介面訪問檔案的資訊

    • boolean isFormField(): isFormField方法用於判斷FileItem類物件封裝的資料是一個普通文字表單欄位,還是一個檔案表單欄位,如果是普通表單欄位則返回true,否則返回false。
    • String getString():用於將FileItem物件中儲存的資料流內容以一個字串返回,它有兩個過載的定義形式:
      public Java.lang.String getString();使用預設的字符集編碼將主體內容轉換成字串
      public java.lang.String getString(java.lang.String encoding) throws java.io.UnsupportedEncodingException
      使用引數指定的字符集編碼將主體內容轉換成字串。如果在讀取普通表單欄位元素的內容時出現了中文亂碼現象,請呼叫第二個getString方法,併為之傳遞正確的字符集編碼名稱
    • void write(File file):用於將FileItem物件中儲存的主體內容儲存到某個指定的檔案中。如果FileItem物件中的主體內容是儲存在某個臨時檔案中,該方法順利完成後,臨時檔案有可能會被清除。該方法也可將普通表單欄位內容寫入到一個檔案中,但它主要用途是將上傳的檔案內容儲存在本地檔案系統中。在此,臨時檔案儲存在專案釋出的tomacat的根目錄下的temp資料夾,但是檔案最終儲存的目錄是upload資料夾
    • long getSize():返回上傳檔案的大小
    • String getName():用於獲得檔案上傳欄位中的檔名。注意IE或FireFox中獲取的檔名是不一樣的,IE中是絕對路徑,FireFox中只是檔名

問題:

      上傳的圖片名字有中文時亂碼,圖片也載入不出來,除錯檢查元素時,手動把.jsp頁面的<img src="">圖片路徑改為中文的也載入不出來,改為不是中文的就能載入出來,把upload.setHeaderEncoding("UTF-8");改為upload.setHeaderEncoding("GBK");就能載入出來了;嘗試使用public java.lang.String getString(java.lang.String encoding) 的建構函式,在此使用改變編碼格式,但是不起作用

總結

這裡寫圖片描述

相關文章