Liferay 內置編輯器功能弱、擴展難。團隊選型 TinyMCE 2.0.8 (成熟穩定、插件豐富) 替換默認編輯器,Liferay 版本 liferay-portal-tomcat-4.1.2。核心挑戰:
advimage 插件實現**圖片上傳** (官方版僅支持外鏈)tinymce_lpackage_zh-cn.jar 解壓至 {$LANGUAGE_PATH}{$LANGUAGE_PATH}/tinymce/jscripts/tiny_mce/* 到 Liferay {$LIFERAY_HOME}/webapps/ROOT/html/js/editor/tinymce/tinymce.jsp,在 tinyMCE.init({...}) 中添加:language : "zh_cn"編輯 {$LIFERAY_HOME}/webapps/ROOT/html/js/editor/tinymce/themes/advanced/editor_template.js 和 simple/editor_template.js:
// 找到 var iFonts = '...' 和 var nFonts = '...'
var iFonts = 'Andale Mono=andale mono;Arial=arial;...;宋體=宋體;方正姚體=方正姚體;微軟雅黑=微軟雅黑';
var nFonts = 'Andale Mono=andale mono;Arial=arial;...;宋體=宋體;方正姚體=方正姚體;微軟雅黑=微軟雅黑';
格式:顯示名=CSS font-family 值,分號分隔。
# 解壓 tinymce_2_0_8.zip
cp -r tinymce/jscripts/tiny_mce {$LIFERAY_HOME}/webapps/ROOT/html/js/editor/tinymce
editor.jsp)<%@ page import="com.liferay.portal.util.Constants" %>
<%@ page import="com.liferay.portal.util.PropsUtil" %>
<%@ page import="com.liferay.util.BrowserSniffer" %>
<%@ page import="com.liferay.util.ParamUtil" %>
<%
String editorImpl = "simple";
if (BrowserSniffer.is_rtf(request)) {
editorImpl = ParamUtil.get(request, "editorImpl", PropsUtil.get(EDITOR_WYSIWYG_IMPL_KEY));
}
// 強制使用 tinymce
editorImpl = "tinymce";
RequestDispatcher rd = application.getRequestDispatcher(Constants.TEXT_HTML_DIR + "/js/editor/" + editorImpl + ".jsp");
rd.include(request, response);
%>
或修改 system.properties:editor.wysiwyg.impl=tinymce。
架構:TinyMCE (前端) → JavaScript 彈窗 → Struts Action (後端上傳) → 返回圖片 URL → 填入編輯器。
FileUploadForm.java (表單 Bean)
package com.family.fileupload.web.form;
import org.apache.struts.action.ActionForm;
import org.apache.struts.upload.FormFile;
public class FileUploadForm extends ActionForm {
private FormFile file;
public FormFile getFile() { return file; }
public void setFile(FormFile file) { this.file = file; }
}
FileUpload.java (工具類,處理流存儲)
package com.family.fileupload.web.utils;
import org.apache.struts.upload.FormFile;
import java.io.*;
public class FileUpload {
private final FormFile file;
private final String extendName;
public FileUpload(FormFile file) {
this.file = file;
this.extendName = file.getFileName().substring(file.getFileName().lastIndexOf('.') + 1).toLowerCase();
}
public void saveToFile(String destPath) throws IOException {
try (InputStream is = file.getInputStream();
OutputStream os = new FileOutputStream(destPath)) {
byte[] buf = new byte[8192];
int len;
while ((len = is.read(buf)) != -1) os.write(buf, 0, len);
}
}
public String getExtendName() { return extendName; }
}
FileUploadAction.java (DispatchAction,處理上傳邏輯)
package com.family.fileupload.web.action;
import javax.servlet.http.*;
import org.apache.struts.action.*;
import org.apache.struts.actions.DispatchAction;
import com.family.fileupload.web.form.FileUploadForm;
import com.family.fileupload.web.utils.FileUpload;
import java.util.Calendar;
import java.util.Date;
public class FileUploadAction extends DispatchAction {
public ActionForward uploadImage(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
FileUploadForm uploadForm = (FileUploadForm) form;
FileUpload fu = new FileUpload(uploadForm.getFile());
String realPath = getServlet().getServletContext().getRealPath("/pictures");
String fileName = genTimestampName() + "." + fu.getExtendName();
String filePath = realPath + "/" + fileName;
fu.saveToFile(filePath);
// 返回可訪問的 URL
String fileUrl = getRootUrl(request) + "/pictures/" + fileName;
request.setAttribute("fileUrl", fileUrl);
return mapping.findForward("image.success");
}
private String genTimestampName() {
Calendar c = Calendar.getInstance();
return String.format("%tY%tm%td%tH%tM%tS", c, c, c, c, c, c); // yyyyMMddHHmmss
}
private String getRootUrl(HttpServletRequest req) {
StringBuffer url = req.getRequestURL();
url.delete(url.length() - req.getRequestURI().length(), url.length());
return url.toString();
}
}
upload.jsp),放入 tinymce/plugins/advimage/<form action="/c/portal/fileUpload?method=uploadImage" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="上傳">
</form>
imagePath.jsp),放入 webapps/ROOT/html/<script>
function insertImage() {
var imageUrl = '<%=(String) request.getAttribute("fileUrl")%>';
if (imageUrl) {
opener.document.all("src").value = imageUrl; // 填入 TinyMCE 圖片對話框的 src 輸入框
window.close();
}
}
insertImage();
</script>
tinymce.jsp 注入文件瀏覽回調function fileBrowserCallBack(field_name, url, type, win) {
// 打開上傳頁面,寬高自定
win.open("upload.jsp", "fileBrowser", "width=400,height=150,resizable=yes,scrollbars=yes");
}
並在 tinyMCE.init 中啟用:file_browser_callback : "fileBrowserCallBack"。
struts-config-ext.xml)<form-beans>
<form-bean name="fileUploadForm" type="com.family.fileupload.web.form.FileUploadForm" />
</form-beans>
<action-mappings>
<action path="/portal/fileUpload"
type="com.family.fileupload.web.action.FileUploadAction"
name="fileUploadForm"
scope="request"
parameter="method">
<forward name="image.success" path="/imagePath.jsp" />
</action>
</action-mappings>
upload.jar{$LIFERAY_HOME}/webapps/ROOT/WEB-INF/lib/tinyMCE 未定義,Firefox 初始化極慢,圖片上傳文件損壞 —— **不推薦**upload.jsp 的 action 指向獨立服務。