文件上傳是B/S系統標配。JSP本身不提供上傳API,需通過ServletRequest.getInputStream()解析原始數據流。本文對比HTTP Multipart(RFC 1867)與FTP協議兩種JavaBean實現方案的原理、代碼骨架與選型建議(環境:Win2000 + Apache + Tomcat 4.0 + JDK 1.4)。
<form method="POST" action="upload.jsp" enctype="multipart/form-data">
<input type="file" name="file1" size="50"><br>
<input type="file" name="file2" size="50"><br>
<input type="submit" value="Upload">
</form>
enctype="multipart/form-data":瀏覽器按RFC 1867編碼,將文件二進制與表單字段混合在請求體中,以boundary分隔各Part。<input type="file">實現多文件並發上傳。testUpload類)public class testUpload {
public testUpload() { ... }
public void initialize(ServletConfig config) throws ServletException { ... }
public void upload() throws UploadException, IOException, ServletException { ... }
private void getDataSection() { ... } // 解析boundary、定位文件數據段
private void getDataHeader() { ... } // 解析Content-Disposition獲取文件名、字段名
public int save(String destPath) throws UploadException, IOException, ServletException { ... }
}
關鍵步驟:
request.getInputStream()獲取原始字節流。Content-Type頭提取boundary字符串。--boundary分割Part,解析每Part頭部(Content-Disposition: form-data; name="file1"; filename="a.txt")。--boundary--標記。| 優點 | 缺點 |
|---|---|
| 瀏覽器原生支持,無需客戶端插件 | 大文件(>100MB)易超時、內存壓力大 |
| 防火牆/代理友好(走80/443端口) | 斷點續傳、並發分塊需前端JS配合複雜 |
| Session天然集成,權限控制簡單 | 單連接吞吐受限於HTTP協議開銷 |
FTPClient)適用於:超大文件、內網高速傳輸、需斷點續傳、服務端存儲與Web服務器分離。
import org.apache.commons.net.ftp.FTPClient;
public class FtpUploader {
public boolean upload(String server, int port, String user, String pass,
String remoteDir, Map<String, InputStream> files) {
FTPClient ftp = new FTPClient();
try {
ftp.connect(server, port);
ftp.login(user, pass);
ftp.enterLocalPassiveMode(); // 關鍵:被動模式穿透防火牆
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
ftp.changeWorkingDirectory(remoteDir);
for (Map.Entry<String, InputStream> e : files.entrySet()) {
ftp.storeFile(e.getKey(), e.getValue()); // 流式直傳
}
ftp.logout();
return true;
} catch (IOException ex) {
ex.printStackTrace();
return false;
} finally {
try { ftp.disconnect(); } catch (IOException ignored) {}
}
}
}
| 優點 | 缺點 |
|---|---|
大文件傳輸穩定,支持斷點續傳(REST/APPE命令) | 需客戶端支持(Applet/ActiveX/HTML5 File API + 後端代理) |
| 傳輸層面無HTTP頭開銷,帶寬利用率高 | 防火牆/NAT穿透複雜(需被動模式+端口範圍開放) |
| 存儲服務器可獨立擴展、異地備份 | 用戶認證體系與Web分離,需同步賬號或Token授權 |
| 場景 | 推薦方案 | 理由 |
|---|---|---|
| 常規業務附件(<50MB)、公網用戶 | HTTP Multipart | 零客戶端依賴、開發最快、權限集成簡單 |
| 大文件(>100MB)、內網高速上傳 | FTP / SFTP | 穩定性、續傳、帶寬效率優勢明顯 |
| 雲原生、對象存儲(OSS/S3) | HTTP直傳OSS(預簽名URL) | 卸載Web服務器帶寬、無限擴展、CDN加速下載 |
| 需客戶端多文件拖拽、進度條、分片上傳 | HTTP + 前端分片庫 + 後端合並 | 現代Web標準體驗,Plupload/Uppy/WebUploader成熟 |
Commons FileUpload或Servlet 3.0@MultipartConfig + request.getPart(),避免手寫解析器。Apache Commons Net或JSch,連接池化FTPClient,避免頻繁握手。協議選型本質是業務場景與基礎設施的匹配。現代架構傾向「HTTP上傳到對象存儲」,FTP逐步退居內部數據交換場景。