1. 程式人生 > 其它 >【Javaweb----檔案上傳】

【Javaweb----檔案上傳】

【Javaweb---檔案上傳】

一、準備工作

匯入包

<dependencies>
    <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.8.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.4</version>
    </dependency>

  </dependencies>

二、建立流程

1、使用類介紹

2、FileItem類

在HTML頁面input必須有name

<input type="file" name="filename">

表單如果包含一個檔案上傳輸入項的話,這個表單的enctype屬性必須設定為multipart/form-data

<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello World!</h2>
</body>

<%--通過表單上傳檔案
get:上傳檔案大小有限制
post:無限制
--%>
<form action = "${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
    上傳使用者:<input type="text" name="username"><br/>
    <p><input type = "file" name="file1"></p>
    <p><input type = "file" name="file1"></p>

    <p><input type = "submit"> | <input type = "reset"></p>

</form>

</html>

3、ServletFileUpload類

ServletFileUpload負責處理上傳的檔案資料,並將表單中每個輸入項封裝成一個FileItem物件,在使用ServletFileUpload物件解析請求時需要DiskFileItemFactory物件。所以,我們需要在進行解析工作前構造好DiskFileItemFactory物件。通過ServletFileUpload物件的構造方法或setFileItemFactory()方法設定ServletFileUpload物件的fileItemFactory屬性。

4、程式碼編寫

FileServlet.java

package com.darkerg.servlet;

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

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

public class FileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //判斷上傳的檔案時普通表單還是帶檔案的表單
        if (!ServletFileUpload.isMultipartContent(req)){
            return;//終止方法執行,說明這是一個普通的表單,直接返回.
        }

        try {
        //建立上傳檔案的儲存路徑,建議在WEB-INF路徑下,安全,使用者無法直接訪問上傳的檔案.
        String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
        File uploadFile = new File(uploadPath);
        if (!uploadFile.exists()){
            uploadFile.mkdir();//建立這個目錄
        }

        //快取,臨時檔案。
        //臨時路徑,加入檔案超過了預期的大小,我們就把他放到一個臨時檔案中,過幾天自動刪除,或者提醒使用者轉存為永久。
        String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
        File file = new File(tmpPath);
        if (!file.exists()){
            file.mkdir();//建立這個目臨時錄
        }

        //處理上傳的檔案,一般都需要通過流來獲取,我們可以使用reqeust.getInputStream(),原生態的檔案上傳流獲取,十分麻煩
        //但是我們都建議使用Apache的檔案上傳元件來實現,common-fileupload,它需要依賴與commons-io元件;

        //ServletFileUpload負責處理上傳的檔案資料,並將表單中每個輸入項分裝成一個FileItem物件,
        //在使用ServletFileUpload物件解析請求時需要DiskFileItemFactory物件。
        //所以,我們需要在進行解析工作前構造好DiskFileItemFactory物件,
        //通過ServletFileUpload物件的構造方法或setFileItemFactory()方法
        //設定ServletFileUpload物件的fileItemFactory屬性


        //1.建立DiskFileItemFactory物件,處理檔案上傳路徑或者大小限制的;
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //通過這個工廠設定一個緩衝區,當上傳的檔案大於這個緩衝區的時候,將他放到臨時檔案中。
        factory.setSizeThreshold(1024 * 1024);//緩衝區大小為1M
        factory.setRepository(file);//臨時目錄的儲存目錄,需要一個File

        //2.獲取ServletFileupload
        ServletFileUpload upload = new ServletFileUpload(factory);

        //監聽檔案上傳進度
        upload.setProgressListener(new ProgressListener() {
            //pBytesRead:已經讀取到的檔案大小
            //pContentLength:檔案大小
            public void update(long pBytesRead, long pContentLength, int pItems) {
                System.out.println("總大小:"+pContentLength+"已上傳:"+pBytesRead);
            }
        });
        //處理亂碼問題
        upload.setHeaderEncoding("UTF-8");
        //設定單個檔案的最大值
        upload.setFileSizeMax(1024 * 1024 * 10);
        //設定總共能夠上傳檔案的大小
        //1024 = 1kb * 1024 =1M * 10 = 10M
        upload.setSizeMax(1024 * 1024 * 10);

        //3.處理上傳的檔案
        //把前端請求解析,封裝成一個FileItem物件,需要從ServletFileUpload物件中獲取 

            List<FileItem> fileItems = upload.parseRequest(req);
            for (FileItem fileItem : fileItems) {
                //判斷山川的檔案時普通的表單還是帶檔案的表單
                if (fileItem.isFormField()){
                    //fileItem  每一個表單物件
                    //getFieldName指的是前端表單控制元件的name;
                    String name = fileItem.getFieldName();
                    String value = fileItem.getString("UTF-8");//處理亂碼
                    System.out.println(name+":"+value);
                }else {//檔案
                    //=======================處理檔案=========================
                    String uploadFileName = fileItem.getName();
                    //可能存在檔名不合法的情況
                    System.out.println("上傳的檔名:"+uploadFileName);
                    if (uploadFileName.trim().equals("") || uploadFileName==null){
                        continue;
                    }
                    //獲得上傳的檔名 /images/girl/paojie.png
                    String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
                    //獲取檔案的字尾名
                    String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
                    /*
                        如果檔案字尾名fileExtName不是我們需要的就直接return,不處理,考蘇使用者檔案型別不對。
                     */
                    //可以使用UUID(唯一識別的通用碼),保證檔名唯一。
                    //UUID.randomUUID(),隨機生成一個唯一識別的通用碼。

                    //網路傳輸中的東西,都需要序列化。
                    //POJO,實體類,如果想要在多個電腦上執行,傳輸====>需要吧物件都序列化了
                    String uuidPath = UUID.randomUUID().toString();
                    //=======================存放地址=========================
                    //存到那兒?uploadPath
                    //檔案真實存在的路徑realPath
                    String realPath = uploadPath + "/" + uuidPath;
                    //給每個檔案建立一個對應的資料夾
                    File realPathFile = new File(realPath);
                    if (!realPathFile.exists()){
                        realPathFile.mkdir();
                    }
                    //=======================檔案傳輸=========================
                    //獲得檔案上傳的流
                    InputStream inputStream = fileItem.getInputStream();

                    //建立一個檔案輸出流
                    //realPath = 真實的資料夾;
                    //差了一個檔案;加上輸出檔案的名字+"/"+uuidFileName
                    FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);

                    //建立一個緩衝區
                    byte[] buffer = new byte[1024 * 1024];

                    //判斷是否讀取完畢
                    int len = 0;
                    //如果大於0說明還存在資料;
                    while ((len=inputStream.read(buffer))>0){
                        fos.write(buffer,0,len);
                    }

                    //關閉流
                    fos.close();
                    inputStream.close();


                }
            }

        } catch (FileUploadException e) {
            e.printStackTrace();
        }


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

三、上傳的檔案在哪裡

通過Maven搭建的,我這邊在Tomcat目錄下的webapps中

通過其它方式搭建,可以尋找專案釋出後的路徑中尋找。