AJAX+Servlet3.0實現非同步檔案上傳(單個檔案、多個檔案上傳、帶檔案的表單提交)
阿新 • • 發佈:2018-12-02
一、上傳單個檔案
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;
}
}