1. 程式人生 > >AJAX+Servlet3.0實現非同步檔案上傳(單個檔案、多個檔案上傳、帶檔案的表單提交)

AJAX+Servlet3.0實現非同步檔案上傳(單個檔案、多個檔案上傳、帶檔案的表單提交)

   一、上傳單個檔案

     

    1.JSP頁面程式碼

     

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="jquery/jquery-3.3.1.js"></script>
<script type="text/javascript" src="bootstrap/bootstrap.js"></script>
<link href="bootstrap/bootstrap.css" rel="stylesheet">
<title>AJAX檔案上傳</title>
<script>
    $(document).ready(function() {
        $("#uploadButton").click(
                function() {                             
                       var xhr;
                       if(window.XMLHttpRequest){
                    	   //IE7+,Firefox,Chrome,Opera,Safari瀏覽器執行的程式碼
                    	   xhr = new XMLHttpRequest();
                       }else{
                    	   //IE6,IE5瀏覽器執行的程式碼
                    	   xhr = new ActiveXObject("Microsoft.XMLHTTP");
                       }                      
                        xhr.open("post","ajaxFileUpload");
                        xhr.onreadystatechange = function() {   
                        	if(xhr.readyState == 4){
                        		 if(xhr.status == 200){
                                     alert("檔案上傳成功"); 
                                 }else{
                                     alert("檔案上傳失敗")
                                 }    
                        	}                         
                        };
                   var file1 = $("#file1")[0].files[0];                
                    var username=$("#userName").val();
                    /* FormData物件用以將資料編譯成鍵值對,以便用XMLHttpRequest來發送資料。其主要用於傳送表單資料,
                                                             但亦可用於傳送帶鍵資料(keyed data),而獨立於表單使用。如果表單enctype屬性設為multipart/form-data ,
                                                               則會使用表單的submit()方法來發送資料,從而,傳送資料具有同樣形式。 */
                    //通過FormData建構函式建立一個空物件
                    var myForm = new FormData();
                    //通過append()方法來追加資料
                    myForm.append("userName",username);
                    myForm.append("file1", file1);   
                    xhr.send(myForm);
                });
    });
</script>
</head>
<body style="margin: 0 auto; text-align: center;">
	<p id="previewImage"></p>
	<form action="fileUpload" enctype="multipart/form-data" method="post">
		<label for="userName">使用者名稱</label> <input type="text" id="userName"
			name="userName" /> <label for="file1">請選擇檔案</label> <input
			type="file" id="file1" name="file1" />
		<button type="button" id="uploadButton" class="btn btn-primary">上傳</button>
	</form>
</body>
</html>

   2.Servlet程式碼

 

   

package com.ajaxuploadtest.app;

import java.io.IOException;
import java.util.Date;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

/*@MultipartConfig標註可用來設定Servlet處理上傳檔案的相關資訊,如果沒有設定屬性則取預設值

可用屬性如下:
1:fileSizeThreshold:整數值設定,若上傳檔案大小超過設定門檻,則先放入快取檔案,預設值為0;
2:location:字串設定,設定寫入檔案時的目錄,如果設定這個屬性值,則快取檔案就是寫到指定的目錄,也可搭配Part的write()方法使用,預設為空字串。
3:maxFileSize:限制上傳檔案大小,預設值為-1L,表示無限制
4:maxRequestSize:限制multipart/form-data請求個數,預設值為-1L,表示不限制個數
*/
@MultipartConfig(location="E:\\uploads", fileSizeThreshold=1024*1024,
maxFileSize=1024*1024*20, maxRequestSize=1024*1024*5*5)
@WebServlet(urlPatterns={"/ajaxFileUpload"},loadOnStartup=1)
public class AjaxFileUpload extends HttpServlet {
    

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        request.setCharacterEncoding("UTF-8");

        //Servlet3.0新增了request.getParts()/getPart(String filename) api,用於獲取使用multipart/form-data格式傳遞的http請求的請求體,通常用於獲取上傳檔案。
        Part part=request.getPart("file1");
        //Servlet3沒有提供直接獲取檔名的方法,需要從請求頭中解析出來
        //獲取請求頭,請求頭的格式:form-data; name="file"; filename="snmp4j--api.zip"
        String header = part.getHeader("content-disposition");
        //獲取檔名
        String fileName = getFileName(header);
        
        System.out.println("fileName:"+fileName);
        part.write(fileName);
        
        response.setContentType("application/json;charset=utf-8");
        
        String s="{\"result\":\"success\"}";
        response.getWriter().print(s);
    }
    
    
    /**
     * 根據請求頭解析出檔名
     * 請求頭的格式:火狐和google瀏覽器下:form-data; name="file"; filename="test.doc"
     *          IE瀏覽器下:form-data; name="file"; filename="E:\test.doc"
     * @param header 請求頭
     * @return 檔名
     */
    public String getFileName(String header) {
        /**
         * String[] tempArr1 = header.split(";");程式碼執行完之後,在不同的瀏覽器下,tempArr1
           數組裡面的內容稍有區別
         * 火狐或者google瀏覽器下:tempArr1={form-data,name="file",filename="test.doc"}
         * IE瀏覽器下:tempArr1={form-data,name="file",filename="E:\test.doc"}
         */
        String[] tempArr1 = header.split(";");
        /**
         *火狐或者google瀏覽器下:tempArr2={filename,"test.doc"}
         *IE瀏覽器下:tempArr2={filename,"E:\test.doc"}
         */
        String[] tempArr2 = tempArr1[2].split("=");
        //獲取檔名,相容各種瀏覽器的寫法
        String fileName = 
           tempArr2[1].substring(tempArr2[1].lastIndexOf("\\")+1).replaceAll("\"", "");
        return fileName;
    }
  

}

   二、上傳帶多個檔案的表單

   

      1.JSP頁面程式碼

    

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="jquery/jquery-3.3.1.js"></script>
<script type="text/javascript" src="bootstrap/bootstrap.js"></script>
<link href="bootstrap/bootstrap.css" rel="stylesheet">
<title>AJAX檔案上傳</title>
<script>
    $(document).ready(function() {
        $("#uploadButton").click(
                function() {                             
                       var xhr;
                       if(window.XMLHttpRequest){
                    	   //IE7+,Firefox,Chrome,Opera,Safari瀏覽器執行的程式碼
                    	   xhr = new XMLHttpRequest();
                       }else{
                    	   //IE6,IE5瀏覽器執行的程式碼
                    	   xhr = new ActiveXObject("Microsoft.XMLHTTP");
                       }                      
                        xhr.open("post","ajaxFileUpload");
                        xhr.onreadystatechange = function() {   
                        	if(xhr.readyState == 4){
                        		 if(xhr.status == 200){
                                     alert("檔案上傳成功"); 
                                 }else{
                                     alert("檔案上傳失敗")
                                 }    
                        	}                         
                        };
                   var file1 = $("#file1")[0].files[0];  
                   var file2 = $("#file2")[0].files[0];
                    var username=$("#userName").val();
                    /* FormData物件用以將資料編譯成鍵值對,以便用XMLHttpRequest來發送資料。其主要用於傳送表單資料,
                                                             但亦可用於傳送帶鍵資料(keyed data),而獨立於表單使用。如果表單enctype屬性設為multipart/form-data ,
                                                               則會使用表單的submit()方法來發送資料,從而,傳送資料具有同樣形式。 */
                    //通過FormData建構函式建立一個空物件
                    var myForm = new FormData();
                    //通過append()方法來追加資料
                    myForm.append("userName",username);
                    myForm.append("file1", file1);  
                    myForm.append("file2", file2);
                    xhr.send(myForm);
                });
    });
</script>
</head>
<body style="margin: 0 auto; text-align: center;">
	<p id="previewImage"></p>
	<form action="fileUpload" enctype="multipart/form-data" method="post">
		<label for="userName">使用者名稱</label> 
		<input type="text" id="userName" name="userName" /><br>
		<label for="file1">請選擇檔案</label>
	    <input type="file" id="file1" name="file1" /><br>
	    <label for="file2">請選擇檔案</label>
	    <input type="file" id="file2" name="file2" /><br>
		<button type="button" id="uploadButton" class="btn btn-primary">提交</button>
	</form>
</body>
</html>

 2.Servlet程式碼

  

package com.ajaxuploadtest.app;

import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

/*@MultipartConfig標註可用來設定Servlet處理上傳檔案的相關資訊,如果沒有設定屬性則取預設值

可用屬性如下:
1:fileSizeThreshold:整數值設定,若上傳檔案大小超過設定門檻,則先放入快取檔案,預設值為0;
2:location:字串設定,設定寫入檔案時的目錄,如果設定這個屬性值,則快取檔案就是寫到指定的目錄,也可搭配Part的write()方法使用,預設為空字串。
3:maxFileSize:限制上傳檔案大小,預設值為-1L,表示無限制
4:maxRequestSize:限制multipart/form-data請求個數,預設值為-1L,表示不限制個數
*/
@MultipartConfig(location = "E:\\uploads", fileSizeThreshold = 1024 * 1024, maxFileSize = 1024 * 1024
		* 20, maxRequestSize = 1024 * 1024 * 10 * 10)
@WebServlet(urlPatterns = { "/ajaxFileUpload" }, loadOnStartup = 1)
public class AjaxFileUpload extends HttpServlet {

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		request.setCharacterEncoding("UTF-8");

		// Servlet3.0新增了request.getParts()/getPart(String filename)
		// api,用於獲取使用multipart/form-data格式傳遞的http請求的請求體,通常用於獲取上傳檔案。
		// 獲取上傳的檔案集合
		Collection<Part> parts = request.getParts();
		System.out.println("parts.size:" + parts.size());
		// 上傳單個檔案
		if (parts.size() == 1) {
			// Servlet3.0將multipart/form-data的POST請求封裝成Part,通過Part對上傳的檔案進行操作。
			// Part part = parts[0];//從上傳的檔案集合中獲取Part物件
			Part part = request.getPart("file1");// 通過表單file控制元件的名字直接獲取Part物件
			// Servlet3沒有提供直接獲取檔名的方法,需要從請求頭中解析出來
			// 獲取請求頭,請求頭的格式:form-data; name="file"; filename="test.doc"
			String header = part.getHeader("content-disposition");
			// 獲取檔名
			String fileName = getFileName(header);
			// 把檔案寫到指定路徑
			part.write(fileName);

		} else {
			// 一次性上傳多個檔案
			// 可以通過Part part = request.getPart("file1");的方式去逐個獲取每個檔案
			// 也可以通過foreach迴圈去處理,這個迴圈方式適合只上傳檔案時。
			for (Part part : parts) {
				// 判斷是否為檔案,如word文件型別為:application/msword,圖片型別為:image開頭,若為普通的資料為null
				String contentType = "" + part.getContentType();
				if (contentType.startsWith("application") || contentType.startsWith("image")) {
					// 獲取請求頭,請求頭的格式:form-data; name="file"; filename="test.doc"
					String header = part.getHeader("content-disposition");
					// 獲取檔名
					String fileName = getFileName(header);
					// 把檔案寫到指定路徑
					part.write(fileName);
				}
			}
		}

		// 獲取表單中普通的資料
		String userName = request.getParameter("userName");
		System.out.println("userName" + userName);

		response.setContentType("application/json;charset=utf-8");

		String s = "{\"result\":\"success\"}";
		response.getWriter().print(s);
	}

	public String getFileName(String header) {
		/**
		 * String[] tempArr1 = header.split(";");程式碼執行完之後,在不同的瀏覽器下,tempArr1數組裡面的內容稍有區別
		 * 火狐或者google瀏覽器下:tempArr1={form-data,name="file",filename="test.doc"}
		 * IE瀏覽器下:tempArr1={form-data,name="file",filename="E:\test.doc"}
		 */
		String[] tempArr1 = header.split(";");
		/**
		 * 火狐或者google瀏覽器下:tempArr2={filename,"test.doc"}
		 * IE瀏覽器下:tempArr2={filename,"E:\test.doc"}
		 */
		String[] tempArr2 = tempArr1[2].split("=");
		// 獲取檔名,相容各種瀏覽器的寫法
		String fileName = tempArr2[1].substring(tempArr2[1].lastIndexOf("\\") + 1).replaceAll("\"", "");
		return fileName;
	}

}