首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2EE

JavaBean 實作檔案上傳(下):完整 Multipart 解析器與進階功能

     編輯:J2EE

完整 FileUploadBean 實作

支援多檔案上傳、一般表單欄位、自動偵測檔名/路徑/Content-Type、可配置儲存目錄。

package com.brainysoftware.web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.ServletInputStream;
import java.util.Dictionary;
import java.util.Hashtable;
import java.io.*;
import java.io.IOException;

public class FileUploadBean {
    private String savePath, filepath, filename, contentType;
    private Dictionary fields;

    // Getter/Setter 略...

    private void setFilename(String header) { /* 解析 Content-Disposition 取得檔名與路徑 */ }
    private void setContentType(String header) { /* 解析 Content-Type 標頭 */ }

    public void doUpload(HttpServletRequest request) throws IOException {
        ServletInputStream in = request.getInputStream();
        byte[] line = new byte[128];
        int i = in.readLine(line, 0, 128);
        if (i < 3) return;
        int boundaryLength = i - 2;
        String boundary = new String(line, 0, boundaryLength);
        fields = new Hashtable();

        while (i != -1) {
            String newLine = new String(line, 0, i);
            if (newLine.startsWith("Content-Disposition: form-data; name=\"")) {
                if (newLine.indexOf("filename=\"") != -1) {
                    // 處理檔案欄位
                    setFilename(new String(line, 0, i-2));
                    if (filename == null) return;
                    i = in.readLine(line, 0, 128); // Content-Type
                    setContentType(new String(line, 0, i-2));
                    i = in.readLine(line, 0, 128); // 空行
                    i = in.readLine(line, 0, 128); // 檔案內容第一行
                    newLine = new String(line, 0, i);
                    PrintWriter pw = new PrintWriter(
                        new BufferedWriter(new FileWriter(
                            (savePath == null ? "" : savePath) + filename)));
                    while (i != -1 && !newLine.startsWith(boundary)) {
                        i = in.readLine(line, 0, 128);
                        if ((i == boundaryLength+2 || i == boundaryLength+4) &&
                            new String(line, 0, i).startsWith(boundary))
                            pw.print(newLine.substring(0, newLine.length()-2));
                        else
                            pw.print(newLine);
                        newLine = new String(line, 0, i);
                    }
                    pw.close();
                } else {
                    // 處理一般表單欄位
                    int pos = newLine.indexOf("name=\"");
                    String fieldName = newLine.substring(pos+6, newLine.length()-3);
                    i = in.readLine(line, 0, 128); // 空行
                    i = in.readLine(line, 0, 128); // 值第一行
                    newLine = new String(line, 0, i);
                    StringBuffer fieldValue = new StringBuffer(128);
                    while (i != -1 && !newLine.startsWith(boundary)) {
                        i = in.readLine(line, 0, 128);
                        if ((i == boundaryLength+2 || i == boundaryLength+4) &&
                            new String(line, 0, i).startsWith(boundary))
                            fieldValue.append(newLine.substring(0, newLine.length()-2));
                        else
                            fieldValue.append(newLine);
                        newLine = new String(line, 0, i);
                    }
                    fields.put(fieldName, fieldValue.toString());
                }
            }
            i = in.readLine(line, 0, 128);
        }
    }
}

核心功能亮點

  • 跨平台檔名處理:Windows 傳送完整路徑,Linux/Mac 僅傳檔名,自動擷取純檔名。
  • 邊界解析:依 RFC 1867 正確識別 multipart 邊界,支援最後一行換行字元修剪。
  • 表單欄位收集:非檔案欄位自動存入 `Dictionary`,供 `getFieldValue()` 取用。
  • 可配置儲存路徑:透過 `setSavePath()` 指定目標目錄。
  • 封裝性佳:單一類別即可部署至任何需上傳功能的 Web 應用。

使用範例

<jsp:useBean id="upload" class="com.brainysoftware.web.FileUploadBean" scope="request" />
<% upload.setSavePath("/var/upload/"); upload.doUpload(request); %>
檔名:<%= upload.getFilename() %><br>
路徑:<%= upload.getFilepath() %><br>
類型:<%= upload.getContentType() %><br>
表單欄位 userName:<%= upload.getFieldValue("userName") %>

部署提醒

  • 若不需套件結構,可移除 `package` 宣告直接編譯。
  • 確保 Servlet 容器支援 `ServletInputStream.readLine()`(標準 API)。
  • 生產環境建議加入檔案大小限制、類型白名單、隨機檔名重命名等安全措施。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved