資料庫準備
CREATE DATABASE test;
USE test;
CREATE TABLE pic (
name VARCHAR(20),
pic BLOB
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
JSP 上傳頁面 (multipart/form-data 必須)
<%@ taglib uri="/struts-tags" prefix="s" %>
<html>
<head><title>圖片上傳</title></head>
<body>
<s:form action="upload" enctype="multipart/form-data">
<s:file name="file" label="選擇圖片" />
<s:textfield name="name" label="圖片名稱" />
<s:submit value="上傳" />
<s:cancel />
</s:form>
</body>
</html>
ActionForm (Struts 1 風格,現代建議 Struts 2 ModelDriven)
package com.example.struts.form;
import org.apache.struts.action.ActionForm;
import org.apache.struts.upload.FormFile;
public class UploadForm extends ActionForm {
private FormFile file;
private String name;
public FormFile getFile() { return file; }
public void setFile(FormFile file) { this.file = file; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
Action 處理邏輯 (核心:二進制流寫入)
package com.example.struts.action;
import java.io.IOException;
import java.sql.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;
import org.apache.struts.upload.FormFile;
import com.example.struts.form.UploadForm;
public class UploadAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
UploadForm uf = (UploadForm) form;
FormFile file = uf.getFile();
String name = uf.getName();
// 基本驗證
if (file == null || file.getFileSize() == 0) {
ActionErrors errors = new ActionErrors();
errors.add("file", new ActionMessage("error.file.required"));
saveErrors(request, errors);
return mapping.findForward("error");
}
Connection conn = null;
PreparedStatement ps = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC";
conn = DriverManager.getConnection(url, "root", "password");
String sql = "INSERT INTO pic (name, pic) VALUES (?, ?)";
ps = conn.prepareStatement(sql);
ps.setString(1, name);
// 關鍵:使用二進制流避免記憶體溢出
ps.setBinaryStream(2, file.getInputStream(), file.getFileSize());
ps.executeUpdate();
return mapping.findForward("success");
} catch (Exception e) {
e.printStackTrace();
return mapping.findForward("error");
} finally {
try { if (ps != null) ps.close(); } catch (SQLException ignored) {}
try { if (conn != null) conn.close(); } catch (SQLException ignored) {}
}
}
}
struts-config.xml 關鍵配置
<form-bean name="uploadForm" type="com.example.struts.form.UploadForm"/>
<action path="/upload"
type="com.example.struts.action.UploadAction"
name="uploadForm"
scope="request"
input="/upload.jsp">
<forward name="success" path="/success.jsp"/>
<forward name="error" path="/error.jsp"/>
</action>
<controller maxFileSize="10M" /> <!-- 限制上傳大小 -->
關鍵技術點總結
| 點 | 說明 |
| enctype | multipart/form-data 必須,否則 FormFile 為 null |
| FormFile | Struts 封裝上傳檔案,提供 getInputStream()/getFileSize()/getFileName() |
| setBinaryStream | JDBC 4.0+ 支援流式寫入 BLOB,大檔案不佔用 JVM 堆記憶體 |
| 連線池 | 生產環境必須使用 DataSource (DBCP/HikariCP/JNDI),禁止手動 DriverManager |
| 異常處理 | finally 區塊確保連線/Statement 關閉,避免洩漏 |
現代化建議 (Struts 2 / Spring MVC / Spring Boot)
- Struts 2:
@Action + File 屬性自動注入,攔截器 fileUpload 處理大小/類型限制。
- Spring MVC:
@PostMapping + MultipartFile,file.getBytes() 或 file.getInputStream()。
- 資料庫層:大物件建議外部儲存 (MinIO/S3/檔案系統),資料庫僅存 URI + 元資料,避免 BLOB 膨脹影響備份/複寫效能。
結語
Struts 上傳圖片存 MySQL BLOB 核心在於 multipart/form-data + FormFile + PreparedStatement.setBinaryStream 三要素。現代架構建議外部物件儲存 + 資料庫元資料,若必須資料庫存儲,使用連線池、流式寫入、完整異常處理,確保穩定可靠。
- 上一篇文章: Webmin 圖形化管理 MySQL 實戰:資料庫建立、表結構設計、權限配置與初始資料匯入
- 下一篇文章: MySQL 綁定特定 IP 監聽配置指南:bind-address 參數、啟動腳本修改與驗證方法
Copyright ©
程式碼之家 All Rights Reserved