富文本編輯器 CKEditor 需要將用戶上傳的圖片存儲到服務器,並返回圖片 URL 供編輯器回顯。本文提供一個基於 Servlet 3.0 + Apache Commons FileUpload 的完整實現,並梳理關鍵配置細節。
multipart/form-data 請求,保存文件,回調 CKEditor。@WebServlet("/upload/image")
public class ImageUploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List<FileItem> items = upload.parseRequest(request);
for (FileItem item : items) {
if (item.isFormField()) continue; // 僅處理文件域
// 生成唯一文件名:yyyyMMddHHmmss + 原始擴展名
String timestamp = DateUtil.getCurrentDateStr();
String ext = item.getName().substring(item.getName().lastIndexOf("."));
String fileName = timestamp + ext;
// 獲取部署絕對路徑:/webapps/ROOT/userImage/
String basePath = getServletContext().getRealPath("/userImage");
File dir = new File(basePath);
if (!dir.exists()) dir.mkdirs();
File savedFile = new File(dir, fileName);
item.write(savedFile);
// CKEditor 要求的回調腳本
String callback = request.getParameter("CKEditorFuncNum");
String fileUrl = request.getContextPath() + "/userImage/" + fileName;
out.println("<script type=\"text/javascript\">");
out.println("window.parent.CKEDITOR.tools.callFunction(" + callback + ",'" + fileUrl + "','');");
out.println("</script>");
out.flush();
}
} catch (Exception e) {
log("圖片上傳失敗", e);
out.println("<script>alert('上傳失敗:" + e.getMessage() + "');</script>");
}
}
}
// DateUtil.java
public class DateUtil {
public static String getCurrentDateStr() {
return new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
}
}
// PropertiesUtil.java(可選,若路徑固定可直接寫死)
public class PropertiesUtil {
public static String getValue(String key) {
try (InputStream in = PropertiesUtil.class.getResourceAsStream("/text.properties")) {
Properties p = new Properties();
p.load(in);
return p.getProperty(key);
} catch (IOException e) { throw new RuntimeException(e); }
}
}
text.propertiesuserImage=userImage/
pageSize=5
imagePath=webapps/ROOT/userImage/
CKEDITOR.replace('editor', {
filebrowserUploadUrl: '/upload/image', // 對應 Servlet 路徑
filebrowserUploadMethod: 'form'
});
| 現象 | 原因 | 解決 |
|---|---|---|
| 上傳後編輯器無圖片 | 回調 URL 錯誤(用了絕對磁碟路徑而非 Web 可訪問路徑) | 返回 request.getContextPath() + "/userImage/xxx.jpg" |
| 中文文件名亂碼 | 未設定編碼或 Tomcat connector 無 URIEncoding | request.setCharacterEncoding("UTF-8"); server.xml 添加 URIEncoding="UTF-8" |
| 大文件上傳失敗 | Commons FileUpload 預設大小限制 | upload.setFileSizeMax(10 * 1024 * 1024); // 10MB |
| 權限拒絕 | 目錄寫入權限不足 | 確保部署用戶對 webapps/ROOT/userImage 有寫權限 |
item.getContentType())。MultipartFile 簡化代碼。掌握上述核心流程與細節,即可快速落地 CKEditor 圖片上傳功能,並避開 90% 的常見問題。