轉自:http://www.cnblogs.com/java_cSharp/archive/2011/08/06/KindEditor_upload_image_plugin.html
前序:由于工作需要使用在線編輯器,找了幾個對比了下KindEditor還是不錯的,國產的.但文檔還是不全,還好能參考官方插件,套出來一些插件.本文章分為4個部分,分別介紹圖片上傳插件、代碼高亮插件、引用文本以及附件插件的制作。網上大部分都是直接或改官方的JSP文件,連action都沒有用,太不專業了。在上傳附件或圖片的時候寫action上傳不了居然還將web.xml中的<url-pattern>/*</url-pattern>換為:<url-pattern>*.action</url-pattern>這樣以來勢必會影響到其他地方。本文主要講解插件的詳細制作過程以及問題的處理,均為結合Struts2的標準方式,絕無什么水貨處理方式!
KindEditor官方:http://www.kindsoft.net/
KindEditor4.0測試版Demo:http://www.kindsoft.net/ke4/php/demo.php
注意:KindEditor官方4.0下月發布正式版,已經有了代碼高亮、附件上傳等插件,如果你能等的話就暫掃一下我的文章就可以了!!!
KindEditor插件之圖片上傳
第一步是什么呢?當然是參考官方的圖片上傳DEMO!
在下載的包中找到jsp/demo.jsp打開看下源碼,直接粘到你的頁面中吧!注意js,css等路徑就行了。fileManager這個是瀏覽遠程圖片的,基本沒人用這個吧?沒什么意義,所以關掉吧!
看下我的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | <%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://"+ request.getServerName() + ":" + request.getServerPort()+ path + "/"; %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> < head > < head > < base href="<%=basePath%>"> < title >KindEditor示例</ title > < link rel = "shortcut icon" type = "image/x-icon" href = "./favicon.png" /> < meta http-equiv = "Content-Type" content = "text/html; charset=utf-8" /> < meta http-equiv = "pragma" content = "no-cache" > < meta http-equiv = "cache-control" content = "no-cache" > < meta http-equiv = "expires" content = "0" > < script src="<%=basePath%>js/jquery.js" type="text/javascript"></ script > < script src="<%=basePath%>js/kindeditor.js" type="text/javascript"></ script > < script type = 'text/javascript' > <!-- $(document).ready(function(){ KE.show({ id : 'content', resizeMode : 1, shadowMode : false, allowPreviewEmoticons : false, allowUpload : true, syncType : 'auto', urlType : 'domain', cssPath : 'css/ke.css', imageUploadJson : '<%=basePath%>fileUpDown/onUploadImg.do', items : [ 'bold', 'italic', 'underline', 'strikethrough', 'removeformat', '|', 'insertorderedlist', 'insertunorderedlist', '|', 'textcolor', 'bgcolor', 'fontname', 'fontsize', '|', 'link', 'unlink', 'emoticons', 'code', 'image', 'flash', 'quote', 'attach', '|', 'selectall', 'source', 'about' ], afterCreate : function(id) { KE.event.ctrl(document, 13, function() { if(KE.isEmpty('content')){ alert('文章為空'); }else{ KE.util.setData(id); document.forms['editform'].submit(); } }); KE.event.ctrl(KE.g[id].iframeDoc, 13, function() { if(KE.isEmpty('content')){ alert('文章為空'); }else{ KE.util.setData(id); document.forms['editform'].submit(); } }); } }); }); var check={ form_submit:function(){ if(KE.isEmpty('content')){ alert('文章為空'); return false; }else{ return true; } } }; //--> </ script > </ head > < body > < form id = "editform" name = "editform" action = "article/showDemo_DemoEditContent.do" method = "post" onsubmit = "return check.form_submit();" > < textarea id = "content" name = "content" style = "width: 580px; height: 250px; visibility: hidden;" ></ textarea > < br /> 您當前輸入了 < span id = "word_count1" >0</ span > 個文字。(字數統計包含HTML代碼。) < br /> 您當前輸入了 < span id = "word_count2" >0</ span > 個文字。(字數統計包含純文本、IMG、EMBED,不包含換行符,IMG和EMBED算一個文字。) < br /> < button id = "id_submit" > 提交 </ button >(提交快捷鍵: Ctrl + Enter) < br /> < input type = "button" name = "button" value = "取得HTML" onclick = "javascript:alert(KE.html('content'));" /> < input type = "button" name = "button" value = "判斷是否為空" onclick = "javascript:alert(KE.isEmpty('content'));" /> < input type = "button" name = "button" value = "取得文本" onclick = "javascript:alert(KE.text('content'));" /> < input type = "button" name = "button" value = "取得文本(包含img,embed)" onclick = "javascript:alert(KE.util.getPureData('content'));" /> < input type = "button" name = "button" value = "取得選中HTML" onclick = "javascript:alert(KE.selectedHtml('content'));" /> < br /> < br /> < input type = "button" name = "button" value = "設置HTML" onclick="javascript:KE.html('content', '<h3>Hello KindEditor</ h3 >');" /> < input type = "button" name = "button" value = "設置文本" onclick="javascript:KE.text('content', '<h3>Hello KindEditor</ h3 >');" /> < input type = "button" name = "button" value = "插入HTML" onclick="javascript:KE.insertHtml('content', '<strong>測試內容</ strong >');" /> < input type = "button" name = "button" value = "添加HTML" onclick="javascript:KE.appendHtml('content', '<strong>Append HTML</ strong >');" /> < input type = "button" name = "button" value = "清空內容" onclick = "javascript:KE.html('content', '');" /> </ form > </ body > </ html > |
imageUploadJson的參數action這個我們還沒有寫呢!不要著急,如果你急的已經部署打開了該頁面你會發現缺了三個圖標,那是我們以后文章中實實在在寫的三個插件的圖標。
cssPath : 'css/ke.css' 這個是編輯器內容里的一些自定義的樣式,比如我們要寫引用文本插件,代碼高亮插件的時候就用得著了!暫時別急,寫上了就寫上了也沒什么問題。我們稍后完成!
第二步寫我們的重中之重的action:
首先聲明下我訪問action的時候結尾不是以action結尾的,我是以do結尾的(你喜歡什么就配什么,改不改無所謂!菜鳥別糾結這個問題),在struts中怎么配置為.do結尾滴呢?
順便給菜鳥補下課:
在src根目錄下創建struts.properties文件,內容為:struts.action.extension=do即可大功告成!!!哇哈哈,簡單嘛?
然后參考解壓包jsp/upload_json.jsp,接下來我們要將其轉換成action
第一步直接寫類吧:
怎么寫?為什么有人說拿不到request的任何參數?還說是KindEditor或Struts2的Bug?污蔑!純屬污蔑,誤人子弟的人們最可恨!
廢話下:struts2對文件上傳進行了包裝,也就是說你可以直接拿到頁面中的file!不需要像寫Servlet那樣寫了!
好直接復制upload_json.jsp的代碼到action中吧?然后改改?
我們要記得在struts2中action獲取文件的時候: 頁面<input type="file" name="imgFile">(哪里來的這個?參看你下載官方壓縮包中的:plugins\image\image.html)
那么action類屬性就應當為:

1 private File imgFile; 2 /** 3 * 文件名稱 4 */ 5 private String imgFileFileName; 6 7 /** 8 * 圖片寬度 9 */10 private String imgWidth;11 12 /**13 * 圖片高度14 */15 private String imgHeight;16 17 /**18 * 圖片對齊方式19 */20 private String align;21 22 /**23 * 圖片標題24 */25 private String imgTitle;
其他的屬性還是和原來action中的寫法一樣,哪里不一樣呢?再給菜鳥補下課:
取文件名的話你的屬性要這么寫:頁面file對象的name+FileName
取文件類型的話你的屬性要這么寫:頁面file對象的name+ContentType
別忘了你的getter\setter方法!!!要不然你真死了都拿不到值!(純屬廢話,我咋那么多廢話?)
action的具體方法請看:

1 public String uploadImg() { 2 3 response.setContentType("text/html; charset=UTF-8"); 4 // 文件保存目錄路徑 5 String savePath = ServletActionContext.getServletContext().getRealPath("/") +"attached/"; 6 // 文件保存目錄URL 7 String saveUrl = request.getContextPath() +"/attached/"; 8 // 定義允許上傳的文件擴展名 9 String[] fileTypes =new String[] { "gif", "jpg", "jpeg", "png", "bmp" };10 // 最大文件大小11 long maxSize = getMaxSize(Constant.FILE_SIZE_IMG);12 PrintWriter out =null;13 try {14 out = response.getWriter();15 } catch (IOException e1) {16 log.error(e1);17 }18 19 if (imgFile ==null) {20 out.println(getError("請選擇文件。"));21 returnnull;22 }23 24 // 檢查目錄25 File uploadDir =new File(savePath);26 if (!uploadDir.isDirectory()) {27 out.println(getError("上傳目錄不存在。"));28 returnnull;29 }30 // 檢查目錄寫權限31 if (!uploadDir.canWrite()) {32 out.println(getError("上傳目錄沒有寫權限。"));33 returnnull;34 }35 // 創建文件夾36 SimpleDateFormat sdf =new SimpleDateFormat("yyyyMMdd");37 String ymd = sdf.format(new Date());38 savePath += ymd +"/";39 saveUrl += ymd +"/";40 File dirFile =new File(savePath);41 if (!dirFile.exists()) {42 dirFile.mkdirs();43 }44 String fileExt = imgFileFileName.substring(imgFileFileName.lastIndexOf(".") +1).toLowerCase();45 if (!Arrays.<String> asList(fileTypes).contains(fileExt)) {46 out.println(getError("上傳文件擴展名["+ fileExt +"]是不允許的擴展名。"));47 returnnull;48 }49 if (imgFile.length() > maxSize) {50 out.println(getError("[ "+ imgFileFileName +" ]超過單個文件大小限制,文件大小[ "+ imgFile.length() +" ],限制為[ "+ maxSize +" ] "));51 returnnull;52 }53 SimpleDateFormat df =new SimpleDateFormat("yyyyMMddHHmmss");54 String newFileName = df.format(new Date()) +"_"+new Random().nextInt(1000) +"."+ fileExt;55 File uploadedFile =new File(savePath, newFileName);56 try {57 FileUtil.Copy(imgFile, uploadedFile);58 JSONObject obj =new JSONObject();59 obj.put("error", 0);60 obj.put("url", saveUrl + newFileName);61 log.debug(obj);62 out.println(obj.toString());63 log.debug("上傳圖片:["+ uploadedFile.getName() +"]"+">>>["+ newFileName +"]成功");64 } catch (IOException e) {65 log.error("圖片上傳失敗:"+ e);66 }67 returnnull;68 }69 private String getError(String message) {70 JSONObject obj =new JSONObject();71 obj.put("error", 1);72 obj.put("message", message);73 log.debug(obj);74 return obj.toString();75 }
然后你問我:getMaxSize(Constant.FILE_SIZE_IMG);哪來的,不好意思我有個配置文件里放的圖片文件限制大小.
如果你想上傳2M的文件那么就應當為:2*1024*1024
FileUtil.Copy(imgFile, uploadedFile);同理,就是個拷貝文件的方法而已沒有什么大不同,這里還牽扯到文件上傳的一個經典問題!
有人說臨時文件沒有刪掉或struts報臨時文件的錯誤.別急一會一起解決掉!
如果你寫到這就著急的運行鳥,那么你傷心的看著404頁面吧....
最后一步:配置struts
1.記得我們剛才改action的訪問后綴了嗎?繼續在剛才的struts.properties中加入:

1 ### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data2 # struts.multipart.parser=cos3 # struts.multipart.parser=pell4 struts.multipart.parser=jakarta5 # uses javax.servlet.context.tempdir by default6 struts.multipart.saveDir=c:\\temp7 # -1 nolimit8 struts.multipart.maxSize=-1
最后一個是上傳文件大小,因為我們在action中配置的,所以這里就直接不限制了.默認2M
中間的是臨時文件存放目錄,我們隨便配吧,默認空所以就跑到你的tomcat下了.
第一個...你想讓我解釋嘛?我X你!X完了就告訴你,那個是說你用什么組件來實現上傳功能!支持commons-fileupload就是默認的jakarta,cos很出名,另一個偶土了沒聽說過.
然后我們忘了我們的action還沒有配置呢!
<action name="onUploadImg" class="xxx.x.UploadAction" method="uploadImg"></action>
我直接指定method方法了...當然你也可以直接默認execute...隨你,最基礎的東西.