1. 程式人生 > 實用技巧 >Java實現檔案上傳

Java實現檔案上傳

一. 注意事項

在Web應用中,檔案上傳和下載功能是非常常用的功能,對於檔案上傳,瀏覽器在上傳的過程中是將檔案以流的形式提交到伺服器端的

【檔案上傳的注意事項】

  • 為保證伺服器安全,上傳檔案應該放在外界無法直接訪問的目錄下,比如放於WEB-INF目錄下
  • 為防止檔案覆蓋的現象發生,要為上傳檔案產生一個唯一的檔名
  • 要限制上傳檔案的最大值
  • 可以限制上傳檔案的型別,在收到上傳檔名時,判斷後綴名是否合法

二. 檔案上傳步驟

1. 下載jar包

1-1.需要jar的地址:
https://mvnrepository.com/artifact/commons-io/commons-io
https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload


1-2.在JavaWeb專案中匯入jar包

1-3.【注意:使用IDEA導包需要注意修復路徑,將lib新增到專案輸出目錄】



2. 編寫upload.jsp

【注意:表單如果包含一個檔案上傳輸入項的話
這個表單的enctype屬性就必須設定multipart/form-data】

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<form action="${pageContext.request.contextPath}/s"
method="post" enctype="multipart/form-data">

<p>上傳使用者:<input type="text" name="username"></p>
<p>上傳檔案:<input type="file" name="file"></p>
<p

><input type="submit"></p>
</form>

</body>
</html>

3. 程式碼編寫 UploadFileServlet

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.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 ServletUpload extends javax.servlet.http.HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    <span class="hljs-keyword">try</span> {

        <span class="hljs-comment">//1.判斷上傳的檔案是普通表單還是帶檔案的表單</span>
        <span class="hljs-keyword">if</span> (!ServletFileUpload.isMultipartContent(req)) {
            <span class="hljs-keyword">return</span>;<span class="hljs-comment">//如果是普通檔案,直接返回</span>
        }<span class="hljs-comment">//通過if就是帶檔案的表單</span>

        <span class="hljs-comment">//2.建立上傳檔案的儲存路徑,建議在WEB-INF路徑下</span>
        <span class="hljs-built_in">String</span> uploadPath = <span class="hljs-keyword">this</span>.getServletContext().getRealPath(<span class="hljs-string">"/WEB-INF/upload"</span>);
        File uploadFile = <span class="hljs-keyword">new</span> File(uploadPath);
        <span class="hljs-keyword">if</span> (!uploadFile.exists()) {
            uploadFile.mkdirs();<span class="hljs-comment">//如果儲存目錄不存在,就建立一個目錄</span>
        }

        <span class="hljs-comment">//3.建立臨時路徑</span>
        <span class="hljs-built_in">String</span> tmpPath = <span class="hljs-keyword">this</span>.getServletContext().getRealPath(<span class="hljs-string">"/WEB-INF/tmp"</span>);
        File tmpFile = <span class="hljs-keyword">new</span> File(tmpPath);
        <span class="hljs-keyword">if</span> (!tmpFile.exists()) {
            tmpFile.mkdirs();<span class="hljs-comment">//如果臨時目錄不存在,就建立一個目錄</span>
        }

        <span class="hljs-comment">//4.建立DiskFileItemFactory物件,處理檔案上傳路徑或者大小限制的;</span>
        DiskFileItemFactory <span class="hljs-keyword">factory</span> = getDiskFileItemFactory(tmpFile);

        <span class="hljs-comment">//5.獲取ServletFileUpload</span>
        ServletFileUpload upload = getServletFileUpload(<span class="hljs-keyword">factory</span>);

        <span class="hljs-comment">//6.處理上傳的檔案</span>
        <span class="hljs-built_in">String</span> msg = uploadParseRequest(upload, req, uploadPath);

        <span class="hljs-comment">//7.servlet請求轉發訊息</span>
        req.setAttribute(<span class="hljs-string">"msg"</span>,msg);
        req.getRequestDispatcher(<span class="hljs-string">"msg.jsp"</span>).forward(req,resp);

    } <span class="hljs-keyword">catch</span> (FileUploadException e) {
        e.printStackTrace();
    }
}

<span class="hljs-comment">//4.建立DiskFileItemFactory物件,處理檔案上傳路徑或者大小限制的;</span>
public <span class="hljs-keyword">static</span> DiskFileItemFactory getDiskFileItemFactory(File tmpFile) {
    DiskFileItemFactory <span class="hljs-keyword">factory</span> = <span class="hljs-keyword">new</span> DiskFileItemFactory();
    <span class="hljs-comment">//4-1.設定一個緩衝區,當上傳檔案大於這個緩衝區的時候,將它放在臨時檔案中</span>
    <span class="hljs-keyword">factory</span>.setSizeThreshold(<span class="hljs-number">1024</span> * <span class="hljs-number">1024</span>);
    <span class="hljs-keyword">factory</span>.setRepository(tmpFile);<span class="hljs-comment">//4-2.臨時目錄的儲存目錄</span>
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">factory</span>;
}

<span class="hljs-comment">//5.獲取ServletFileUpload</span>
public <span class="hljs-keyword">static</span> ServletFileUpload getServletFileUpload(DiskFileItemFactory <span class="hljs-keyword">factory</span>) {
    ServletFileUpload upload = <span class="hljs-keyword">new</span> ServletFileUpload(<span class="hljs-keyword">factory</span>);
    <span class="hljs-comment">//5-1.監聽檔案上傳進度</span>
    upload.setProgressListener(<span class="hljs-keyword">new</span> ProgressListener() {
        <span class="hljs-meta">@Override</span>
        <span class="hljs-comment">//5-2.l:已經讀取到檔案的大小</span>
        <span class="hljs-comment">//5-3.l1:檔案大小</span>
        public <span class="hljs-keyword">void</span> update(long l, long l1, <span class="hljs-built_in">int</span> i) {
            System.out.println(<span class="hljs-string">"總大小:"</span> + l1 + <span class="hljs-string">"\t"</span> + <span class="hljs-string">"已上傳:"</span> + l);
        }
    });
    upload.setHeaderEncoding(<span class="hljs-string">"utf-8"</span>);<span class="hljs-comment">//5-4.處理亂碼問題</span>
    upload.setFileSizeMax(<span class="hljs-number">1024</span> * <span class="hljs-number">1024</span> * <span class="hljs-number">10</span>);<span class="hljs-comment">//5-5.設定單個檔案的最大值</span>
    upload.setSizeMax(<span class="hljs-number">1024</span> * <span class="hljs-number">1024</span> * <span class="hljs-number">10</span>);<span class="hljs-comment">//5-6.設定總共能夠上傳檔案的大小</span>
    <span class="hljs-keyword">return</span> upload;
}

<span class="hljs-comment">//6.處理上傳的檔案</span>
public <span class="hljs-keyword">static</span> <span class="hljs-built_in">String</span> uploadParseRequest(ServletFileUpload upload, HttpServletRequest req, <span class="hljs-built_in">String</span> uploadPath)
        throws FileUploadException, IOException {
    <span class="hljs-built_in">String</span> msg = <span class="hljs-string">""</span>;

    <span class="hljs-comment">//6-1.把前端請求解析,封裝成一個FileItem物件</span>
    <span class="hljs-built_in">List</span>&lt;FileItem&gt; fileItems = upload.parseRequest(req);
    <span class="hljs-keyword">for</span> (FileItem fileItem : fileItems) {
        <span class="hljs-keyword">if</span> (fileItem.isFormField()) {<span class="hljs-comment">//6-2.判斷上傳的檔案是普通的表單還是帶檔案的表單</span>
            <span class="hljs-built_in">String</span> name = fileItem.getFieldName();
            <span class="hljs-built_in">String</span> value = fileItem.getString(<span class="hljs-string">"utf-8"</span>);<span class="hljs-comment">//6-3.處理 亂碼</span>
        } <span class="hljs-keyword">else</span> {<span class="hljs-comment">//6-4.判斷它是上傳檔案</span>

            <span class="hljs-comment">//6-5.拿到檔名字</span>
            <span class="hljs-built_in">String</span> uploadFileName = fileItem.getName();
            System.out.println(<span class="hljs-string">"上傳的檔名:"</span> + uploadFileName);
            <span class="hljs-keyword">if</span> (uploadFileName.trim().equals(<span class="hljs-string">""</span>) || uploadFileName == <span class="hljs-keyword">null</span>) {
                <span class="hljs-keyword">continue</span>;
            }

            <span class="hljs-comment">//6-6.獲得上傳檔名</span>
            <span class="hljs-built_in">String</span> fileName = uploadFileName.substring(uploadFileName.lastIndexOf(<span class="hljs-string">"/"</span>) + <span class="hljs-number">1</span>);
            <span class="hljs-comment">//6-7.獲得檔案的字尾名</span>
            <span class="hljs-built_in">String</span> fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(<span class="hljs-string">"."</span>) + <span class="hljs-number">1</span>);
            System.out.println(<span class="hljs-string">"檔案資訊 [檔名:"</span> + fileName + <span class="hljs-string">"---檔案型別"</span> + fileExtName + <span class="hljs-string">"]"</span>);
            <span class="hljs-comment">//6-8.使用UUID(唯一識別的通用碼),保證檔名唯一</span>
            <span class="hljs-built_in">String</span> uuidPath = UUID.randomUUID().toString();
            <span class="hljs-comment">//6-9.檔案真實存在的路徑 realPath</span>
            <span class="hljs-built_in">String</span> realPath = uploadPath + <span class="hljs-string">"/"</span> + uuidPath;
            <span class="hljs-comment">//6-10.給每個檔案建立一個對應的資料夾</span>
            File realPathFile = <span class="hljs-keyword">new</span> File(realPath);
            <span class="hljs-keyword">if</span> (!realPathFile.exists()) {
                realPathFile.mkdir();
            }

            <span class="hljs-comment">//6-11.獲得檔案上傳的流</span>
            InputStream inputStream = fileItem.getInputStream();
            <span class="hljs-comment">//6-12.建立一個檔案輸出流</span>
            <span class="hljs-comment">//6-13.realPath = 真實的資料夾;</span>
            <span class="hljs-comment">//6-14.差了一個檔案; 加上輸出檔案的名字+"/"+uuidFileName</span>
            FileOutputStream fos = <span class="hljs-keyword">new</span> FileOutputStream(realPath + <span class="hljs-string">"/"</span> + fileName);
            <span class="hljs-comment">//6-15.建立一個緩衝區</span>
            byte[] buffer = <span class="hljs-keyword">new</span> byte[<span class="hljs-number">1024</span> * <span class="hljs-number">1024</span>];
            <span class="hljs-comment">//6-16.判斷是否讀取完畢</span>
            <span class="hljs-built_in">int</span> len = <span class="hljs-number">0</span>;
            <span class="hljs-comment">//6-17.如果大於0說明還存在資料;</span>
            <span class="hljs-keyword">while</span> ((len = inputStream.read(buffer)) &gt; <span class="hljs-number">0</span>) {
                fos.write(buffer, <span class="hljs-number">0</span>, len);
            }

            <span class="hljs-comment">//6-18.關閉流</span>
            fos.close();
            inputStream.close();

            msg = <span class="hljs-string">"檔案上傳成功!"</span>;
            fileItem.delete();<span class="hljs-comment">//6-19.上傳成功,清除臨時檔案</span>
        }
    }
    <span class="hljs-keyword">return</span> msg;
}


<span class="hljs-meta">@Override</span>
protected <span class="hljs-keyword">void</span> doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     doGet(req, resp);
}

}

4. 編寫msg.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
${msg}
</body>
</html>

5. 配置web.xml

   <servlet>
        <servlet-name>ServletFileUpload</servlet-name>
        <servlet-class>com.sz.ServletUpload</servlet-class>
    </servlet>
<span class="hljs-tag">&lt;<span class="hljs-name">servlet-mapping</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">servlet-name</span>&gt;</span>ServletFileUpload<span class="hljs-tag">&lt;/<span class="hljs-name">servlet-name</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">url-pattern</span>&gt;</span>/s<span class="hljs-tag">&lt;/<span class="hljs-name">url-pattern</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">servlet-mapping</span>&gt;</span>