1. 程式人生 > >用commons-fileupload實現檔案上傳

用commons-fileupload實現檔案上傳

Form表單的要求

1.提供from表單,method必須是post(post方式可以提交大量資料)

2.提供input type=”file”標籤

3.form表單的enctype屬性必須是multipart/form-data(就是在設定請求訊息頭的Content-Type)

  • application/x-www-form-urlencoded(預設)。請求報文內容的格式為name=admin&password=123。伺服器通過request.getParameter(“name”);來獲取資料
  • multipart/form-data。請求報文內容的格式為
Content-Type
: multipart/form-data; boundary=---------------------------28512195225210 Content-Length: 295 -----------------------------28512195225210 Content-Disposition: form-data; name="a" q -----------------------------28512195225210 Content-Disposition: form-data; name="b"; filename="a.txt" Content-Type: text
/plain eaglezsx -----------------------------28512195225210--

資料被分隔線分成一段一段的,其中每兩個分隔線之間的資料稱為一個item。request.getParameter(“name”)方法獲取指定的表單欄位字元內容,但檔案上傳表單已經不再是字元內容,而是位元組內容,所以失效。用request.getInputStream();方法可以獲取位元組流。

例子

新建一個a.txt,裡邊隨便寫點兒東西,eaglezsx。

新建一個upload.jsp

<form enctype="multipart/form-data"
action="${pageContext.request.contextPath}/servlet/uploadServlet" method="post"> <input type="text" name="a" /> <input type="file" name="b"/></br> <input type="submit" value="提交"/> </form>

新建一個Servlet,UploadServlet.java

public class UploadServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        ServletInputStream sis=request.getInputStream();//獲取請求報文中的內容
        int len=-1;
        byte[] b=new byte[1024];
        while ((len=sis.read(b))!=-1) {
            System.out.println(new String(b,0,len));//將請求報文中的內容轉化為字串,列印到控制檯
        }
        sis.close();

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

執行結果為

-----------------------------17157105472171
Content-Disposition: form-data; name="a"

hello
-----------------------------17157105472171
Content-Disposition: form-data; name="b"; filename="a.txt"
Content-Type: text/plain

eaglezsx
-----------------------------17157105472171--

這就是從瀏覽器接收到的那些東西。把這些東西解析了,就可以獲得需要的內容了。自己解析起來比較麻煩。有現成的元件commons fileupload來解析這些請求。Apache的官網有它的使用者指南http://commons.apache.org/proper/commons-fileupload/using.html裡邊有個小例子。

在使用FileUpload元件時,需要匯入commons-fileupload和commons-io兩個jar包。

通過這個例子,可以看出主要用這幾樣東西

DiskFileItemFactory類

如果上傳的檔案比較小,將儲存在記憶體中。如果上傳的檔案比較大,則會以臨時檔案的形式儲存在磁碟的臨時資料夾中。預設情況下,檔案儲存在記憶體還是硬碟臨時資料夾的臨界值是10240,即10K。

構造方法

  • DiskFileItemFactory():採用預設臨界值10240,預設臨時資料夾為D:\Java\apache-tomcat-7.0.52\temp,Tomcat安裝目錄中的temp資料夾中。
  • DiskFileItemFactory(int sizeThreshold,File repository):採用引數指定臨界值和臨時檔案的儲存位置

方法

  • setSizeThreshold(int sizeThreshold):設定臨界值
  • setRepository(File repository):設定臨時檔案的儲存位置

ServletFileUpload類

構造方法:

  • ServletFileUpload(FileItemFactory fileItemFactory)

方法:

  • parseRequest(HttpServletRequest req):解析出Form表單中的每個欄位的資料,並將它們分別包裝成獨立的FileItem物件,然後將這些FileItem物件加入進一個List型別的集合物件中返回。
  • isMultipartContent():是個靜態方法,判斷請求訊息中的內容是否是multipart/form-data型別,如果是則返回true。

FileItem介面

  • boolean isFormFiled():用於判斷FileItem類物件封裝的資料是一個普通文字表單欄位,還是一個檔案表單欄位,如果是普通表單欄位則返回true。
  • String getFiledName():獲取表單欄位name屬性的值。
  • String getName():獲取檔案上傳欄位中的檔名
  • String getString():獲取普通欄位的value屬性的值。
  • String getString(String encoding):可以設定編碼,這樣普通標籤的value為中文時就不會亂碼了
  • void write(File file):將FileItem物件中儲存的主體內容儲存到某個指定的檔案中。如果內容是在臨時檔案中,那麼DiskFileItem被垃圾回收後,臨時檔案會被自動刪除。

  • String getContentType():獲取上傳檔案的型別,即表單欄位描述頭屬性Content-Type的值,如“image/jpeg”。

  • boolean isInMemory():判斷FileItem物件封裝的資料內容是儲存在記憶體中,還是儲存在臨時檔案中,在記憶體中則返回true。
  • long getSize():返回該上傳檔案的大小(以位元組為單位)
  • InputStream getInputStream():以流的形式返回上傳檔案的內容
public class UploadServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        if (ServletFileUpload.isMultipartContent(request)) {

            File repository=new File("G:/");
            DiskFileItemFactory factory=new DiskFileItemFactory(1024*1024, repository);

            ServletFileUpload upload=new ServletFileUpload(factory);

            try {
                List<FileItem> items=upload.parseRequest(request);//這句話執行就會開始產生臨時檔案,這句話執行完後,臨時檔案也就產生了,臨時檔案和上傳的檔案一樣大,後面的操作都是對臨時檔案的操作
                for (FileItem item : items) {
                    if (item.isFormField()) {
                        processFormField(item);
                    }else {
                        try {
                            processUploadedFile(item);
                        } catch (Exception e) {

                            e.printStackTrace();
                        }
                    }
                }


            } catch (FileUploadException e) {

                e.printStackTrace();
            }

        }else {
            System.out.println("這不是檔案上傳表單");
        }

    }

    private void processUploadedFile(FileItem item) throws Exception {
        String fieldName=item.getFieldName();
        String fileName=item.getName();
        String contentType=item.getContentType();
        boolean isInMemory=item.isInMemory();
        long sizeInBytes=item.getSize();

        System.out.println(fieldName+" "+fileName+" "+contentType+" "+" "+isInMemory+" "+sizeInBytes);

        //把上傳的檔案儲存d盤
        File uploadedFile=new File("D:/"+fileName);

        item.write(uploadedFile);//這種方式臨時檔案會自動刪除

        //或者採用流的形式操作資料,這種方式需要呼叫delete方法來刪除臨時檔案
        /*
        InputStream uploadedStream=item.getInputStream();
        FileOutputStream fos=new FileOutputStream(uploadedFile);
        int len=0;
        byte[] b=new byte[1024];
        while((len=uploadedStream.read(b))!=-1){
            fos.write(b,0,len);
        }
        uploadedStream.close();
        fos.close();
        item.delete();
        */
    }

    private void processFormField(FileItem item) {
        String name=item.getFieldName();
        String value=item.getString();

        System.out.println("name:"+name+"---"+"value:"+value);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

顯示結果為

name:a---value:hello
b a.txt text/plain  true 8

需要注意的問題

1.getName()在有的瀏覽器中獲取的是檔名(a.txt),但在有些瀏覽器中獲取的就是完整的路徑(C:\Users\YZ\Desktop\a.txt)。

解決方法

String filename=fileitem.getName();
filename=filename.substring(filename.lastIndexOf(File.separator)+1);
filename=FilenameUtils.getName(filename);

2.如果客戶端上傳了一個jsp,上面寫著一段讓伺服器關機的程式碼。之後客戶端訪問這個jsp,jsp裡邊的程式碼就會執行。

為了保證伺服器的安全,把上傳檔案的目錄放在使用者訪問不到的地方。WEB-INF下

File uploadedFile=new File(this.getServletContext().getRealPath("/WEB-INF/uploadedfile"));

3.如果上傳的檔名稱相同,以前的檔案會被覆蓋

讓檔名唯一即可

filename=UUID.randomUUID()+"_"+filename;

4.把檔案都放到一個資料夾裡到時候檢索的時候會很慢

把檔案打散,弄一些子目錄

  • 通過日期打散
File uploadedFile=new File(this.getServletContext().getRealPath("/WEB-INF/uploadedfile"));
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
String date=sdf.format(new Date());
uploadedFile=new File(uploadedFile,date);
  • 通過雜湊值打散
int hashcode=fileName.hashCode();//返回此物件的雜湊值
String code=Integer.toHexString(hashcode);//將其轉換為16進位制的字元,se3343ie
String childDirectory=code.charAt(0)+File.separator+code.charAt(1);// s/e
uploadedFile=new File(uploadedFile,childDirectory);

5.限制檔案的大小

ServletFileUpload中的

  • setFileSizeMax(位元組):設定單個檔案的大小
  • setSizeMax(位元組):總檔案大小(多檔案上傳)

6.使用者沒有選擇檔案,就點選了上傳

判斷檔名是否為空即可

7.檔名為中文時會亂碼。

用ServletFileUpload的setHeaderEncoding方法設定一下。

8.普通欄位的value為中文時會亂碼

String value=item.getString("utf-8");

用Streaming API實現上傳

前面用的是傳統的API實現上傳,commons-fileupload還有一套Streaming API。官方文件http://commons.apache.org/proper/commons-fileupload/streaming.html說這種方法沒有傳統方法便利,但效能更好。傳統方法有多便利我沒看出來(有知道的,麻煩告訴我一下),但Streaming API在效能上的提升確可以明顯的看出來。傳統方法中,上傳的檔案都要先儲存到記憶體或臨時檔案中,然後在對記憶體或臨時檔案進行操作。這樣的話,如果我上傳的大檔案,相當於操作了檔案兩遍,先把上傳檔案弄到快取檔案中,再把快取檔案複製一份到最終目錄。如果用Streaming API的話,直接把上傳的檔案傳到最終的目錄。

public class UploadServlet2 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        if (ServletFileUpload.isMultipartContent(request)) {

            ServletFileUpload upload=new ServletFileUpload();
            try {
                FileItemIterator iter = upload.getItemIterator(request);

                while(iter.hasNext()){
                    FileItemStream item=iter.next();
                    String name=item.getFieldName();//獲取name屬性的值

                    if(item.isFormField()){
                        processFormField(item);
                    }else{
                        processUploadedFile(item);
                    }
                }

            } catch (FileUploadException e) {

                e.printStackTrace();
            }


        }else {
            System.out.println("這不是檔案上傳表單");
        }

    }

    private void processUploadedFile(FileItemStream item) throws IOException{

        InputStream is=item.openStream();
        FileOutputStream fos=new FileOutputStream(new File("D:/"+item.getName()));

        int len=-1;
        byte[] b=new byte[1024*1024];
        while((len=is.read(b))!=-1){
            fos.write(b, 0, len);
        }
        is.close();
        fos.close();

    }

    private void processFormField(FileItemStream item) throws IOException {
        String name=item.getFieldName();
        InputStream is=item.openStream();
        String value=Streams.asString(is);


        System.out.println("name:"+name+"---"+"value:"+value);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

相關推薦

commons-fileupload實現檔案

Form表單的要求 1.提供from表單,method必須是post(post方式可以提交大量資料) 2.提供input type=”file”標籤 3.form表單的enctype屬性必須是multipart/form-data(就是在設定請求訊息頭的C

Apache Commons FileUpload實現檔案

Commons FileUpload簡介 Apache Commons是一個專注於可重用Java元件開發的 Apache 專案。Apache Commons專案由三個部分組成: 1、Commons Proper - 可重用Java元件的儲存庫。 2、The Commons Sandbox - 用於Jav

commons-fileupload實現檔案

一、準備需要上傳的檔案 上傳檔案的準備就不用多說了,先準備一個jsp頁面。此頁面中有一個form表單,此表單有如下三個特徵。 a、表單的method必須是post b、表單的enctyp

commons-fileupload實現檔案、下載、線上開啟

最近做了一個檔案上傳、下載、與線上開啟檔案的功能,剛開始對檔案上傳的介面中含有其它表單(例如輸入框、密碼等)在上傳的過程中遇到了許多問題,下面我寫了一個同時實現檔案上傳、下載、線上開啟檔案的測試程式。 首先請看效果圖: 核心程式碼:

利用 Commons-Fileupload 實現檔案

Apache FileUpload檔案上傳元件API解析(轉) Java Web開發人員可以使用Apache檔案上傳元件來接收瀏覽器上傳的檔案,該元件由多個類共同組成,但是,對於使用該元件來編寫檔案上傳功能的Java Web開發人員來說,只需要瞭解和使用其中的三個類:DiskFileUpload、FileIt

SpringMVC 通過commons-fileupload實現檔案

[TOC](目錄) # 配置 ## web.xml ```xml ``` ## SpringMVC配置檔案 applicationContext.xml 上傳檔案的核心配置類:CommonsMultipartResolver,注意`id="multipartResolver"`不要寫錯 ```

Java架構-Spring mvc+oss儲存+fileupload檔案實現SSO單點登入模板管理

之前給大家介紹了sso的相關知識點和整合方案,考慮到每個系統所屬行業的不同,這邊針對於不同行業做了一些統一的sso單點登入介面模板,使用fileupload多檔案上傳+OSS阿里雲端儲存方案。 1. 阿里雲oss儲存Utils Java程式碼 2. 阿里雲配

框架中如何根據fileupload工具包實現檔案功能

工具包 Apache-fileupload.jar – 檔案上傳核心包。 Apache-commons-io.jar – 這個包是fileupload的依賴包。同時又是一個工具包。 程式碼  servletFileUpload官方API /*獲取tomcat的wor

socket自定義簡單協議實現檔案與接受

一個上傳的資料包,主要包含檔案頭和檔案內容倆部分,主要按下面的格式,傳送: "File-Name:xxxxxx.zip;File-Type:exe;File-Length:1029292\r\n" ------檔案內容--------- 1、服務端的檔案接受服務 MySoc

檔案控制元件Fileupload實現檔案並寫入資料庫)

首先我們來說一下Fileupload這個檔案上傳控制元件的幾大敗筆: 1.上傳之後按F5重新整理,重複提交 2.提交以後按後退鍵Fileupload中的資訊還在 3.不支援多檔案上傳 4.上傳前不能檢測檔案大小 解決方法: 1.建立iframe在子頁面實現或者重定向語句(R

httpUrlConnection實現檔案

1、事先了解 1.1 請求格式 我們使用http來上傳檔案,必須先了解http的請求格式,然後才好發報。主要分為以下四個部分: (1)分界符:由兩個連字元“--”和任意字串組成; (2)標準http報文格式,來形容上傳檔案的相關資訊,包括請求引數名,上傳檔名,檔案型別,接收

php 通過ssh2協議sftp實現檔案、下載

伺服器的連線 $connection=ssh2_connect($host, $port); if( ssh2_auth_pubkey_file($connection, $send_account,

common-fileUpload和 Spring中MultipartHttpServletRequest實現檔案、以及過濾器的問題

遇到一個專案中寫的過濾器有些不明白為什麼那麼寫,其實就是以下的第二部分不理解造成的 二、 使用servlet時:多部件表單上傳對servlet取值問題 1)  request.getParameter("..."),這個方法在表單為multiparty/form-d

SmartUpload實現檔案

首先要匯入SmartUpload.jar包 連結地址:http://pan.baidu.com/s/1eStyDZc 示例: index.jsp  <body>     <fo

commons.fileupload 文件

session val sta ava 工廠 ota data 自定義 this 編輯jsp頁面獲取文件 1 <html> 2 <head> 3 <base href="<%=basePath%>"> 4

struts2實現檔案與下載功能

一、Demo介紹 基於struts2框架,實現多檔案的上傳和下載功能。 實現原理圖: 部分介面圖: 上傳成功及下載頁面: 二、主要程式碼 uploadFile.jsp:在form表單中包含一個文字框(上傳使用者的姓名)和兩個檔案上傳選項. <%@

Java Springboot結合FastDFS實現檔案以及根據圖片url將圖片至圖片伺服器

上一篇文章我們已經講解了如何搭建FastDFS圖片伺服器,環境我們準備好了現在就讓我們開始與Java結合將他應用到實際的專案中吧。本篇文章我們將會展示上傳圖片到FastDFS圖片伺服器以及通過外網的圖片url將圖片上傳至我們自己的圖片伺服器中。 1.建立springbo

yii框架實現檔案

yii框架實現檔案上傳 1.首先yii框架下載uploadFile類 2.html程式碼 <input type="file" class="file" style="display: none" name="business_license" /> 3.j

原生javascript實現檔案功能程式碼

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, ini