本文提供一套基於 HTML5 FormData + XMLHttpRequest 前端,配合 Java Servlet(Apache Commons FileUpload)後端的大文件上傳完整示例。支持超 1GB 大文件,採用流式寫入避免內存溢出。
<input id="fileid" type="file" accept="video/*;capture=camera" onchange="onfile(this)">
<input id="btn" type="button" value="提交">
<script>
var xhr;
function onfile(file) {
var fd = new FormData();
fd.append("fileToUpload", document.getElementById('fileid').files[0]);
xhr = new XMLHttpRequest();
xhr.open("POST", "https://localhost:8889/TestUp/upservlet");
// 注意:不可手動設置 Content-Type,瀏覽器會自動生成 multipart/form-data 邊界
xhr.send(fd);
xhr.onreadystatechange = processResponse;
}
function processResponse() {
if (xhr.readyState == 4) {
if (xhr.status == 200) alert("服務器響應: " + xhr.responseText);
else alert("上傳失敗");
}
}
</script>
關鍵點:FormData 自動處理 multipart/form-data 編碼;切勿手動設置 Content-Type,否則會導致邊界缺失解析失敗。
依賴兩個 JAR:commons-fileupload-1.2.1.jar、commons-io-1.3.2.jar。
public class UpServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String savePath = getServletContext().getRealPath("/WEB-INF/upload");
File dir = new File(savePath);
if (!dir.exists()) dir.mkdirs();
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8"); // 解決文件名中文亂碼
if (!ServletFileUpload.isMultipartContent(request)) return;
List<FileItem> items = upload.parseRequest(request);
for (FileItem item : items) {
if (item.isFormField()) {
// 普通表單字段處理
String value = item.getString("UTF-8");
} else {
// 文件字段處理
String filename = item.getName();
if (filename == null || filename.trim().isEmpty()) continue;
// 截取純文件名(去除路徑)
filename = filename.substring(filename.lastIndexOf("\\") + 1);
try (InputStream in = item.getInputStream();
FileOutputStream out = new FileOutputStream(savePath + File.separator + filename)) {
byte[] buffer = new byte[1024 * 1024]; // 1MB 緩衝區
int len;
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
}
item.delete(); // 清理臨時文件
}
}
request.setAttribute("message", "上傳成功");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
}
FileItem.getInputStream() 逐塊讀取,避免全量載入內存。item.delete() 釋放磁盤空間。upload.setHeaderEncoding("UTF-8") 解決文件名亂碼。WEB-INF 下,防止直接外部訪問。web.xml 中 Servlet 映射、max-file-size/max-request-size 限制。<meta charset="UTF-8">,後端 setHeaderEncoding("UTF-8")。DiskFileItemFactory 閾值,超過閾值寫入臨時文件而非內存。此方案經測試可穩定支持 1GB+ 視頻文件上傳,適合內部管理系統、素材庫等場景。生產環境建議增加斷點續傳、MD5 秒傳、分片上傳等增強功能。