Apache Commons FileUpload實現文件上傳


一、Apache Commons-FileUpload簡介

Apache Commons是一個專注於可重用Java組件的所有方面的 Apache 項目。
Apache Commons項目由三個部分組成:

  • Commons Proper - 可重用Java組件的存儲庫。
  • The Commons Sandbox - 用於Java組件開發的工作區。
  • The Commons Dormant - 當前不活動的組件存儲庫。

Commons-FileUpload是Commons Proper中的一個組件,該組件依賴於Commons-IO ,Commons-IO也是 Commons Proper中的一個組件。
Commons FileUpload的JAR包下載
Commons IO的JAR包下載

二.maven依賴

<!-- upload file -->
        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>

三.前端界面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <% String path = request.getContextPath(); %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>upload</title>
</head>
<br>
<br>

<form action="<%=path%>/device/uploadFile" method ="post" enctype="multipart/form-data">
    <input type ="file" name ="doc1"><br><br>
    <input type ="file" name ="doc2"><br><br>
    <input type ="text" name = info><br><br>
    <input type ="password" name ="password"><br><br>
    
    <input type="submit" value="提交">
</form>

<body>

</body>
</html>

四.后台代碼

@RequestMapping(value="/uploadFile")
    public String uploadFile(final HttpServletRequest request, final HttpServletResponse response){         
    
        request.setAttribute("msg", "Not first time!");        
         //創建一個“硬盤文件條目工廠”對象
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //設置閾值,設置JVM一次能夠處理的文件大小(默認吞吐量是10KB)
        factory.setSizeThreshold(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD);
        //設置臨時文件的存儲位置(文件大小大於吞吐量的話就必須設置這個值,比如文件大小:1GB ,一次吞吐量:1MB)
         factory.setRepository(new File("d:\\test"));
        //創建核心對象
         ServletFileUpload fileUpload = new ServletFileUpload(factory);
        //設置最大可支持的文件大小(10MB)
         fileUpload.setFileSizeMax(1024*1024*10);
        //設置轉換時使用的字符集
         fileUpload.setHeaderEncoding("UTF-8");
         if(ServletFileUpload.isMultipartContent(request)){
             try {
                List<FileItem> fileItems = fileUpload.parseRequest(request);
                for ( FileItem fileItem : fileItems) {
                    if(fileItem.isFormField()){//判斷該FileItem為一個普通的form元素
                        //獲取字段名
                        String fieldName = fileItem.getFieldName();
                        //獲取字段值,並解決亂碼
                        String fieldValue = fileItem.getString("UTF-8");
                        System.out.println(fieldName +" : " + fieldValue);
                        
                    }else{//判斷該FileItem為一個文件
                        
                        System.out.println("Start to uplaod file!");
                        //獲取文件名
                        String fileName = fileItem.getName();
                        System.out.println("fileName : " + fileName);
                        //獲取文件大小
                        long fileSize = fileItem.getSize();
                        System.out.println("fileSize : " + fileSize);
                        
                        fileItem.write(new File("D://test//upload"+File.separator +fileName));
                    }
                }
            } catch (FileUploadException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
         }
        
    return "device/uploadFile";
    }

 五。異常

catch(FileUploadBase.SizeLimitExceededException ex){
                out.print("上傳失敗,文件太大,單個文件的最大限制是:"+upload.getSizeMax()+"bytes!");    
}

1.其中需要注意的是流的操作,和File類的操作,mkdirs()和mkdir()的區別是什么?它們都是用來創建文件夾的,區別在mkdirs能創建多級目錄,而mkdir()只能創建當前的文件夾,如果發現上一層目錄並還沒有創建時,它也會無動於衷,什么也不干,也就不能創建當前文件夾,必須先要創建了上一級文件夾才可以。

2.上面還有很多的問題需要解決,比如上傳文件名的亂碼問題,比如單表內容的亂碼問題,比如上傳文件同名問題,如果上傳的文件很大,該如何進行處理,比如,放在同一級目錄下的文件過多如何處理。每次都自己手動寫輸出流,將內容存到指定位置,太過麻煩,等等問題,現在寫一個加強版,在解決上面所有的問題。

3.上傳文件名亂碼問題:使用servletFileUpload.setHeaderEncoding("UTF-8");或者request.setCharacterEncoding("UTF-8")都可以

4.表單內容亂碼問題:使用getString("utf-8")即可,也就是在獲取內容時,就可以設置碼表。

5.上傳文件同名問題:使用UUID.randomUUID().toString().replace("-", "").獲得一個獨一無二的32位數字

6.使用FileUtils.copyInputStreamToFile(is, file);來將內容輸出到指定路徑文件中去,mkdirs() 自動創建目錄

7.同一級目錄下的文件過多問題:創建多級目錄,通過文件名的hashcode的值,hashCode為int型,占4個字節,一個字節占8位,也就是占32位,將其分組,4位4位一組,就能分8組,每一次代表一層目錄,也就能夠分8層目錄,每一層中,有可以創建16種不同的文件夾。這樣算下來,就能有很多很多個文件夾了,每個文件夾下面都可以存很多文件,看我們的業務需求,來決定要創建幾層目錄,就從hashcode中拿幾組數據出來。原理圖如下

            

 生成兩級目錄
public class StringUtils {

    /**
     * 生成二級目錄
     * @param fileName  abc.txt
     * @return  /4/5
     */
    public static String getDir(String fileName) {
        //1 hashCode值
        int hashCode = fileName.hashCode();
        System.out.println(hashCode);
        //2 第一層 0xf表示15的16進制數。
        int dir1 = hashCode & 0xf;
        //3 第二層目錄
        int dir2 = hashCode >>> 4 & 0xf;
        
        //4 拼寫
        return "/" + dir1 + "/" + dir2;
    }
    
    public static void main(String[] args) {
        System.out.println(getDir("abc.txt"));
    }

}

總結上傳:

        其實理解了也不是很難,就是上傳文件后的處理比較麻煩,各種小問題,存儲過程最為麻煩。

        1、創建工廠類

        2、使用核心類,

        3、解析request請求,

        4、遍歷請求體的內容,將上傳內容和普通表單內容都獲取出來

        5、獲取到上傳內容時,對其存儲位置進行設置

        其中很多細節問題都在上面已經說清楚了,代碼中也有很多注釋。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM