Java 專案需求高效能檔案上傳時,手寫 Servlet 易出錯且難維護。主流選擇為 jakarta commons-fileupload 與 smartupload。實測後者大檔上傳易出錯、中文支援不佳,故採用前者。本文提供完整封裝類別與前後端整合範例。
<form name="Form1" onSubmit="return check()" enctype="multipart/form-data" method="post" action="uploadResult.jsp">
<input type="checkbox" name="checkbox" value="ch1"> 公共資料夾
<input type="hidden" name="ch1" id="ch1" size="20">
<input type="checkbox" name="checkbox" value="ch2"> 測試資料夾
<input type="hidden" name="ch2" id="ch2" size="20">
<p>選擇 Excel 檔案 <input type="file" name="File1" size="20" maxlength="20"></p>
<p>注意:請確保為 Excel 格式,檔名勿含空格,同名自動覆蓋</p>
<input type="submit" value="提交"> <input type="reset" value="取消">
</form>
<script>
function check() {
if (document.Form1.checkbox[0].checked) document.Form1.ch1.value = document.Form1.checkbox[0].value;
if (document.Form1.checkbox[1].checked) document.Form1.ch2.value = document.Form1.checkbox[1].value;
var newAction = Form1.action + "?ch1=" + document.Form1.ch1.value + "&ch2=" + document.Form1.ch2.value;
Form1.action = newAction;
}
</script>
<%
String temp = "C:\\TEMP";
char[] label = new char[2];
String labelString = "";
// 初始化標記陣列
for (int i = 0; i < label.length; i++) label[i] = '0';
String des = request.getRealPath("/FinancialReports/ExcelFile");
// 依 checkbox 決定上傳子目錄
if (request.getParameterValues("ch1") != null) {
String[] ch1 = request.getParameterValues("ch1");
if (ch1[0].equals("ch1")) label[0] = '1';
}
if (request.getParameterValues("ch2") != null) {
String[] ch2 = request.getParameterValues("ch2");
if (ch2[0].equals("ch2")) label[1] = '1';
}
for (int i = 0; i < label.length; i++) labelString += label[i];
des = des + "\\" + labelString;
Fileupload fileUpload = new Fileupload(temp, des, request);
boolean uploadResult = fileUpload.Upload(true);
%>
package net.hyweb;
import java.io.File;
import java.util.*;
import org.apache.commons.fileupload.*;
import javax.servlet.http.HttpServletRequest;
public class Fileupload {
private String tempPath = "C:\\TEMP";
private String destinationPath;
private HttpServletRequest fileuploadRequest;
private int sizeThreshold = 4096; // 記憶體緩衝閾值 (bytes)
private long sizeMax = 10485760; // 最大上傳 10MB
public Fileupload() {}
public Fileupload(String tempPath, String destinationPath) {
this.tempPath = tempPath;
this.destinationPath = destinationPath;
}
public Fileupload(String tempPath, String destinationPath, HttpServletRequest request) {
this(tempPath, destinationPath);
this.fileuploadRequest = request;
}
public boolean Upload() {
// 確保暫存與目標目錄存在
ensureDirectory(tempPath);
ensureDirectory(destinationPath);
DiskFileUpload fu = new DiskFileUpload();
fu.setSizeThreshold(sizeThreshold);
fu.setSizeMax(sizeMax);
fu.setRepositoryPath(tempPath);
List fileItems;
try {
fileItems = fu.parseRequest(fileuploadRequest);
} catch (FileUploadException e) {
e.printStackTrace();
return false;
}
Iterator iter = fileItems.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (!item.isFormField()) { // 檔案欄位
String fieldName = item.getFieldName();
String name = item.getName();
if (name == null || name.equals("") || item.getSize() == 0) continue;
String fileName = getFileName(name);
try {
item.write(new File(destinationPath + fileName));
} catch (Exception e) {
e.printStackTrace();
return false;
}
} else { // 一般表單欄位
// 可依需求處理其他參數
}
}
return true;
}
private void ensureDirectory(String path) {
File dir = new File(path);
if (!dir.isDirectory()) {
try { dir.mkdirs(); }
catch (SecurityException e) { System.out.println("無法建立目錄: " + path); }
}
}
public String getFileName(String filepath) {
String filename = "*.*";
if (filepath != null && filepath.length() > 0) {
filepath = filepath.replace('\\', '/');
int idx = filepath.lastIndexOf('/');
if (idx >= 0) filename = filepath.substring(idx + 1);
}
return filename;
}
// 省略 getter/setter
}
| 參數 | 預設值 | 說明 |
|---|---|---|
| sizeThreshold | 4096 bytes | 超過此大小改寫入暫存檔,避免記憶體溢位 |
| sizeMax | 10 MB | 限制單次上傳總大小,防止 DoS |
| repositoryPath | tempPath | 暫存檔存放目錄 |
commons-fileupload.jar 與 commons-io.jarenctype="multipart/form-data"sizeMax 並加入檔案類型驗證原始碼開源,引用請註明出處:Huang ye (www.hyweb.net)