FCKeditor - The text editor for Internet
蒋 いつ峰 2008/06/12   |  Rich Client
Java との統合 -- FCKeditor-2.3-java とファイル アップロード 2008/06/12  |  PK:FCKeditor java ファイルアップロード

Javaウェブ・アプリケーションでFCKeditorを使う。また、FCKeditor を利用してファイル(写真とFlashなど)をアップロードし、簡単にコンテンツに挿入できる。簡単に管理と運用できるため、アップロードされたファイルのサーバ上の保存場所と名前について、カスタマイズし、「/${htdocs}/UserFiles/userid/type/yyyymmddzzzz.ext」のようにします。例えば、「http://uprush.net/UserFiles/2/Image/200710156978.jpg」のように保存します。

1.FCKeditor-2.3-javaのインストール

こちら から、最新バージョンの統合用ファイルをダウンロードできます。

ダウンロードしたファイルに含まれるFCKeditor-2.3.jarを直接使えますが、日本語名ファイルはアップロードで きない、また、アップロード・ファイルの保存場所と名前をカスタマイズしたいので、ソースを修正して利用します。解凍した「FCKeditor-2.3- java/src/FCKeditor.tld」を WEB-INF/tld にコピーする。「FCKeditor-2.3-java/src/com」フォルダをプロジェクトのソースフォルダにコピーする、例えばUprushの場 合は uprush/src です。

ファイル・アップロードについて、Apache の commons-fileupload が必要となります。FCKeditor-2.3-java にあるcommons-fileupload はバージョンが古いため、日本語名ファイルのアップロードができない。Apache から最新版ダウンロードし、commons-fileupload-1.2.jar をWEB-INF/lib に配置する。

 

ConnectorとSimpleUploader のservlet を指定する。web.xml に下記内容を追加する。

 
  1. <servlet>  
  2.     <servlet-name>Connector</servlet-name>  
  3.     <servlet-class>com.fredck.FCKeditor.connector.ConnectorServlet</servlet-class>  
  4.     <init-param>  
  5.         <param-name>baseDir</param-name>  
  6.         <param-value>/UserFiles/</param-value>  
  7.     </init-param>  
  8.     <init-param>  
  9.         <param-name>debug</param-name>  
  10.         <param-value>false</param-value>  
  11.     </init-param>  
  12.     <load-on-startup>1</load-on-startup>  
  13. </servlet>  
  14.   
  15. <servlet>  
  16.     <servlet-name>SimpleUploader</servlet-name>  
  17.     <servlet-class>com.fredck.FCKeditor.uploader.SimpleUploaderServlet</servlet-class>  
  18.     <init-param>  
  19.         <param-name>baseDir</param-name>  
  20.         <param-value>/UserFiles/</param-value>  
  21.     </init-param>  
  22.     <init-param>  
  23.         <param-name>debug</param-name>  
  24.         <param-value>false</param-value>  
  25.     </init-param>  
  26.     <init-param>  
  27.         <param-name>enabled</param-name>  
  28.         <param-value>true</param-value>  
  29.     </init-param>  
  30.     <init-param>  
  31.         <param-name>AllowedExtensionsFile</param-name>  
  32.         <param-value></param-value>  
  33.     </init-param>  
  34.     <init-param>  
  35.         <param-name>DeniedExtensionsFile</param-name>  
  36.         <param-value>php|php3|php5|phtml|asp|aspx|ascx|jsp|cfm|cfc|pl|bat|exe|dll|reg|cgi</param-value>  
  37.     </init-param>  
  38.     <init-param>  
  39.         <param-name>AllowedExtensionsImage</param-name>  
  40.         <param-value>jpg|gif|jpeg|png|bmp</param-value>  
  41.     </init-param>  
  42.     <init-param>  
  43.         <param-name>DeniedExtensionsImage</param-name>  
  44.         <param-value></param-value>  
  45.     </init-param>  
  46.     <init-param>  
  47.         <param-name>AllowedExtensionsFlash</param-name>  
  48.         <param-value>swf|fla</param-value>  
  49.     </init-param>  
  50.     <init-param>  
  51.         <param-name>DeniedExtensionsFlash</param-name>  
  52.         <param-value></param-value>  
  53.     </init-param>  
  54.     <load-on-startup>1</load-on-startup>  
  55. </servlet>  
  56. <servlet-mapping>  
  57.   <servlet-name>Connector</servlet-name>  
  58.   <url-pattern>/fckeditor/editor/filemanager/browser/default/connectors/jsp/connector</url-pattern>  
  59. </servlet-mapping>  
  60.    
  61. <servlet-mapping>  
  62.   <servlet-name>SimpleUploader</servlet-name>  
  63.   <url-pattern>/fckeditor/editor/filemanager/upload/simpleuploader</url-pattern>  
  64. </servlet-mapping>  

 

 fckeditor/fckconfig.js を修正する。

 
  1. // FCKConfig.LinkUploadURL = FCKConfig.BasePath + ’filemanager/connectors/’ + _QuickUploadLanguage + ’/upload.’ + _QuickUploadExtension ;  
  2. FCKConfig.LinkUploadURL = FCKConfig.BasePath + ’filemanager/upload/simpleuploader?Type=File’ ;  
  3.   
  4. // FCKConfig.ImageUploadURL = FCKConfig.BasePath + ’filemanager/connectors/’ + _QuickUploadLanguage + ’/upload.’ + _QuickUploadExtension + ’?Type=Image’ ;  
  5. FCKConfig.ImageUploadURL = FCKConfig.BasePath + ’filemanager/upload/simpleuploader?Type=Image’ ;  
  6.   
  7. // FCKConfig.FlashUploadURL = FCKConfig.BasePath + ’filemanager/connectors/’ + _QuickUploadLanguage + ’/upload.’ + _QuickUploadExtension + ’?Type=Flash’ ;  
  8. FCKConfig.FlashUploadURL = FCKConfig.BasePath + ’filemanager/upload/simpleuploader?Type=Flash’ ;  

 

最後、FCKeditor を取り込むJSPを修正する。

FCKeditor の taglib をインポートする。

  1. <%@ taglib uri="/WEB-INF/tld/FCKeditor.tld" prefix="FCK" %>  

FCKeditor を取り込む

 
  1. <FCK:editor  
  2.     id="FCKeditor1"  
  3.     basePath="fckeditor/"  
  4.     height="600"  
  5.     defaultLanguage="Ja">  
  6. </FCK:editor>  

 

 TomcatなどのAPサーバを起動し、ブラウザのキャッシュを消してから上記JSPにアクセスと、FCKeditor が画面に表示されるはずです。エディタの「イメージ挿入/編集」をクリックと下記画面が表示される。

 

2.サーバ・ブラウザを無効化

上記写真、Flashのアップロード画面に、「サーバーブラウザー」ボタンがあります。このボタンをクリックすると、アップロードされたファイルを保存するサーバー上のフォルダの内容が見えます。外向けのサーバにとって、この機能が好ましくないです。無効にする。fckeditor/fckconfig.js を修正する。

 
  1. // FCKConfig.LinkBrowser = true ;  
  2. FCKConfig.LinkBrowser = false ;  
  3.   
  4. // FCKConfig.ImageBrowser = true ;  
  5. FCKConfig.ImageBrowser = false ;  
  6.   
  7. // FCKConfig.FlashBrowser = true ;  
  8. FCKConfig.FlashBrowser = false ;  

 

ブラウザのキャッシュを消して確認すると、アップロード画面の「サーバーブラウザー」は消えた。

 

3.アップロード先のカスタマイズ

以上で FCKeditor と Java は連携できましたが、ファイルのアップロード、特に日本語名ファイルのアップロードにはまだ修正が必要です。

FCKeditor-java を使ってアップロードしたファイルは、デフォルト「$PROJECT_ROOT/UserFiles/type/filename」でサーバ上に保存されます。ファイル数が多くなると管理が難しくなります。ですので、保存フォルダを「${htdocs}/UserFiles/userid/type」、ファイル名を「yyyymmddzzzz.ext」にします。例えば、「/var/www/html/UserFiles/101/Image/200801160001.gif」として保存します。
先FCKeditor-2.3-javaのソースをプロジェクトにコピーしました。ソース com.fredck.FCKeditor.uploader.SimpleUploaderServlet を修正します。

ここの ${htdocs} はウェブ・コンテンツのフォルダを指します、例えば「/var/www/html」、値は設定ファイル(.properties)から取得します。

 
  1. String htdocDir = _rb.getString("htdocs_folder");  

 

コンテンツを掲載するには、ログインが必要で、ユーザIDをセッションに保存すると想定します。ですので、userid はセッションから取得できます。

 
  1. HttpSession session = request.getSession();  
  2. if (session != null) {  
  3.     Object userid = session.getAttribute(USER_ID_KEY);  
  4.     if (userid != null) {  
  5.         currentPath = currentPath + (String) userid;  
  6.     }  
  7. }  


ファイル名は「日付+乱数+拡張子」(yyyymmddzzzz.ext)にします。

 
  1. private String getFileID() {  
  2.     int ranNum = RandomUtils.nextInt(10000);  
  3.     Calendar c = Calendar.getInstance();  
  4.     String year = String.valueOf(c.get(Calendar.YEAR));  
  5.     String month = StringUtils.leftPad(String.valueOf(c.get(Calendar.MONTH) + 1), 2’0’);  
  6.     String day = StringUtils.leftPad(String.valueOf(c.get(Calendar.DAY_OF_MONTH)), 2’0’);  
  7.     String ret = year + month + day + String.valueOf(ranNum);  
  8.       
  9.     return ret;  
  10. }  

 

以下は修正後の SimpleUploaderServlet の完全なソースです。

 
  1. /* 
  2.  * FCKeditor - The text editor for internet 
  3.  * Copyright (C) 2003-2005 Frederico Caldeira Knabben 
  4.  *  
  5.  * Licensed under the terms of the GNU Lesser General Public License: 
  6.  *      http://www.opensource.org/licenses/lgpl-license.php 
  7.  *  
  8.  * For further information visit: 
  9.  *      http://www.fckeditor.net/ 
  10.  *  
  11.  * File Name: SimpleUploaderServlet.java 
  12.  *  Java File Uploader class. 
  13.  *  
  14.  * Version:  2.3 
  15.  * Modified: 2005-08-11 16:29:00 
  16.  *  
  17.  * File Authors: 
  18.  *      Simone Chiaretta (simo@users.sourceforge.net) 
  19.  */   
  20. package com.fredck.FCKeditor.uploader;  
  21.   
  22. import java.io.File;  
  23. import java.io.IOException;  
  24. import java.io.PrintWriter;  
  25. import java.util.ArrayList;  
  26. import java.util.Calendar;  
  27. import java.util.HashMap;  
  28. import java.util.Hashtable;  
  29. import java.util.Iterator;  
  30. import java.util.List;  
  31. import java.util.Map;  
  32. import java.util.ResourceBundle;  
  33.   
  34. import javax.servlet.ServletException;  
  35. import javax.servlet.http.HttpServlet;  
  36. import javax.servlet.http.HttpServletRequest;  
  37. import javax.servlet.http.HttpServletResponse;  
  38. import javax.servlet.http.HttpSession;  
  39.   
  40. import org.apache.commons.fileupload.FileItem;  
  41. import org.apache.commons.fileupload.disk.DiskFileItemFactory;  
  42. import org.apache.commons.fileupload.servlet.ServletFileUpload;  
  43. import org.apache.commons.lang.StringUtils;  
  44. import org.apache.commons.lang.math.RandomUtils;  
  45.   
  46.   
  47. /** 
  48.  * Servlet to upload files.<br> 
  49.  * 
  50.  * This servlet accepts just file uploads, eventually with a parameter specifying file type 
  51.  * 
  52.  * @author Simone Chiaretta (simo@users.sourceforge.net) 
  53.  */  
  54. public class SimpleUploaderServlet extends HttpServlet {  
  55.       
  56.     private static String baseDir;  
  57.     private static boolean debug=false;  
  58.     private static boolean enabled=false;  
  59.     private static Hashtable allowedExtensions;  
  60.     private static Hashtable deniedExtensions;  
  61.     private static ResourceBundle _rb = ResourceBundle.getBundle("resource.uprush");  
  62.       
  63.     /** 
  64.      * UserID session key 
  65.      */  
  66.     private static final String USER_ID_KEY = "USER_ID_MEMO";  
  67.       
  68.     /** 
  69.      * Initialize the servlet.<br> 
  70.      * Retrieve from the servlet configuration the "baseDir" which is the root of the file repository:<br> 
  71.      * If not specified the value of "/UserFiles/" will be used.<br> 
  72.      * Also it retrieve all allowed and denied extensions to be handled. 
  73.      * 
  74.      */  
  75.      public void init() throws ServletException {  
  76.           
  77.         debug=(new Boolean(getInitParameter("debug"))).booleanValue();  
  78.           
  79.         if(debug) System.out.println("\r\n---- SimpleUploaderServlet initialization started ----");  
  80.           
  81.         baseDir=getInitParameter("baseDir");  
  82.         enabled=(new Boolean(getInitParameter("enabled"))).booleanValue();  
  83.         if(baseDir==null)  
  84.             baseDir="/UserFiles/";  
  85.         // String realBaseDir=getServletContext().getRealPath(baseDir);  
  86.         String htdocDir = _rb.getString("htdocs_folder");  
  87.         // File baseFile=new File(realBaseDir);  
  88.         File baseFile=new File(htdocDir + baseDir);  
  89.         if(!baseFile.exists()){  
  90.             baseFile.mkdir();  
  91.         }  
  92.           
  93.         allowedExtensions = new Hashtable(3);  
  94.         deniedExtensions = new Hashtable(3);  
  95.                   
  96.         allowedExtensions.put("File",stringToArrayList(getInitParameter("AllowedExtensionsFile")));  
  97.         deniedExtensions.put("File",stringToArrayList(getInitParameter("DeniedExtensionsFile")));  
  98.   
  99.         allowedExtensions.put("Image",stringToArrayList(getInitParameter("AllowedExtensionsImage")));  
  100.         deniedExtensions.put("Image",stringToArrayList(getInitParameter("DeniedExtensionsImage")));  
  101.           
  102.         allowedExtensions.put("Flash",stringToArrayList(getInitParameter("AllowedExtensionsFlash")));  
  103.         deniedExtensions.put("Flash",stringToArrayList(getInitParameter("DeniedExtensionsFlash")));  
  104.           
  105.         if(debug) System.out.println("---- SimpleUploaderServlet initialization completed ----\r\n");  
  106.           
  107.     }  
  108.       
  109.   
  110.     /** 
  111.      * Manage the Upload requests.<br> 
  112.      * 
  113.      * The servlet accepts commands sent in the following format:<br> 
  114.      * simpleUploader?Type=ResourceType<br><br> 
  115.      * It store the file (renaming it in case a file with the same name exists) and then return an HTML file 
  116.      * with a javascript command in it. 
  117.      * 
  118.      */   
  119.     public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  120.   
  121.         if (debug) System.out.println("--- BEGIN DOPOST ---");  
  122.   
  123.         response.setContentType("text/html; charset=UTF-8");  
  124.         response.setHeader("Cache-Control","no-cache");  
  125.         PrintWriter out = response.getWriter();  
  126.           
  127.   
  128.         String typeStr=request.getParameter("Type");  
  129.           
  130.         String currentPath=baseDir;  
  131.           
  132.         // upload フォルダを 「/${htdocs}/UserFiles/userid/type」 にする  
  133.           
  134.         // 会員ID  
  135.         HttpSession session = request.getSession();  
  136.         if (session != null) {  
  137.             Object userid = session.getAttribute(USER_ID_KEY);  
  138.             if (userid != null) {  
  139.                 currentPath = currentPath + (String) userid;  
  140.             }  
  141.         }  
  142.         currentPath = currentPath + "/" + typeStr;  
  143.           
  144.         // String currentDirPath=getServletContext().getRealPath(currentPath);  
  145.         String currentDirPath = _rb.getString("htdocs_folder") + currentPath;  
  146.           
  147.         // フォルダが存在しない場合、フォルダを作成する  
  148.         File folder = new File(currentDirPath);  
  149.         if (!folder.exists()) {  
  150.             folder.mkdirs();  
  151.         }  
  152.           
  153.         // fileUrl を ${htdocs_folder} の相対パスにする  
  154.         // currentPath=request.getContextPath()+currentPath;  
  155.           
  156.         if (debug) System.out.println(currentDirPath);  
  157.           
  158.         String retVal="0";  
  159.         String newName="";  
  160.         String fileUrl="";  
  161.         String errorMessage="";  
  162.           
  163.         if(enabled) {         
  164.             // DiskFileUpload upload = new DiskFileUpload();  
  165.             ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());  
  166.             try {  
  167.                 List items = upload.parseRequest(request);  
  168.                   
  169.                 Map fields=new HashMap();  
  170.                   
  171.                 Iterator iter = items.iterator();  
  172.                 while (iter.hasNext()) {  
  173.                     FileItem item = (FileItem) iter.next();  
  174.                     if (item.isFormField())  
  175.                         fields.put(item.getFieldName(),item.getString());  
  176.                     else  
  177.                         fields.put(item.getFieldName(),item);  
  178.                 }  
  179.                 FileItem uplFile=(FileItem)fields.get("NewFile");  
  180.                 String fileNameLong=uplFile.getName();  
  181.                 fileNameLong=fileNameLong.replace(’\\’,’/’);  
  182.                 String[] pathParts=fileNameLong.split("/");  
  183.                 String fileName=pathParts[pathParts.length-1];  
  184.                   
  185.                 // create unique filename 「yyyymmddzzzz.ext」  
  186.                 String nameWithoutExt=getFileID();  
  187.                 String ext=getExtension(fileName);  
  188.                 fileName = nameWithoutExt + "." + ext;  
  189.                 File pathToSave=new File(currentDirPath, fileName);  
  190.                 fileUrl=currentPath+"/"+fileName;  
  191.                 if(extIsAllowed(typeStr, ext)) {  
  192.                     int counter=1;  
  193.                     while(pathToSave.exists()){  
  194.                         newName=nameWithoutExt+ "(" + counter + ")" + "." + ext;  
  195.                         fileUrl=currentPath+"/"+newName;  
  196.                         retVal="201";  
  197.                         pathToSave=new File(currentDirPath, newName);  
  198.                         counter++;  
  199.                         }  
  200.                     uplFile.write(pathToSave);  
  201.                 }  
  202.                 else {  
  203.                     retVal="202";  
  204.                     errorMessage="";  
  205.                     if (debug) System.out.println("Invalid file type: " + ext);   
  206.                 }  
  207.             }catch (Exception ex) {  
  208.                 if (debug) ex.printStackTrace();  
  209.                 retVal="203";  
  210.             }  
  211.         }  
  212.         else {  
  213.             retVal="1";  
  214.             errorMessage="This file uploader is disabled. Please check the WEB-INF/web.xml file";  
  215.         }     
  216.           
  217.         out.println("<script type=\"text/javascript\">");  
  218.         out.println("window.parent.OnUploadCompleted("+retVal+",’"+fileUrl+"’,’"+newName+"’,’"+errorMessage+"’);");  
  219.         out.println("</script>");  
  220.         out.flush();  
  221.         out.close();  
  222.       
  223.         if (debug) System.out.println("--- END DOPOST ---");      
  224.           
  225.     }  
  226.   
  227.   
  228.     /* 
  229.      * This method was fixed after Kris Barnhoorn (kurioskronic) submitted SF bug #991489 
  230.      */  
  231.     private static String getNameWithoutExtension(String fileName) {  
  232.             return fileName.substring(0, fileName.lastIndexOf("."));  
  233.         }  
  234.           
  235.     /* 
  236.      * This method was fixed after Kris Barnhoorn (kurioskronic) submitted SF bug #991489 
  237.      */  
  238.     private String getExtension(String fileName) {  
  239.         return fileName.substring(fileName.lastIndexOf(".")+1);  
  240.     }  
  241.   
  242.   
  243.     /** 
  244.      * Helper function to convert the configuration string to an ArrayList. 
  245.      */  
  246.      private ArrayList stringToArrayList(String str) {  
  247.        
  248.      if(debug) System.out.println(str);  
  249.      String[] strArr=str.split("\\|");  
  250.            
  251.      ArrayList tmp=new ArrayList();  
  252.      if(str.length()>0) {  
  253.          for(int i=0;i<strArr.length;++i) {  
  254.                 if(debug) System.out.println(i +" - "+strArr[i]);  
  255.                 tmp.add(strArr[i].toLowerCase());  
  256.             }  
  257.         }  
  258.         return tmp;  
  259.      }  
  260.   
  261.   
  262.     /** 
  263.      * Helper function to verify if a file extension is allowed or not allowed. 
  264.      */  
  265.      private boolean extIsAllowed(String fileType, String ext) {  
  266.               
  267.             ext=ext.toLowerCase();  
  268.               
  269.             ArrayList allowList=(ArrayList)allowedExtensions.get(fileType);  
  270.             ArrayList denyList=(ArrayList)deniedExtensions.get(fileType);  
  271.               
  272.             if(allowList.size()==0)  
  273.                 if(denyList.contains(ext))  
  274.                     return false;  
  275.                 else  
  276.                     return true;  
  277.   
  278.             if(denyList.size()==0)  
  279.                 if(allowList.contains(ext))  
  280.                     return true;  
  281.                 else  
  282.                     return false;  
  283.        
  284.             return false;  
  285.      }  
  286.   
  287.      /** 
  288.       * Random なファイル名を作成する。 
  289.       *  
  290.       * @return Random なファイル名 
  291.       */  
  292.      private String getFileID() {  
  293.          int ranNum = RandomUtils.nextInt(10000);  
  294.          Calendar c = Calendar.getInstance();  
  295.          String year = String.valueOf(c.get(Calendar.YEAR));  
  296.          String month = StringUtils.leftPad(String.valueOf(c.get(Calendar.MONTH) + 1), 2’0’);  
  297.          String day = StringUtils.leftPad(String.valueOf(c.get(Calendar.DAY_OF_MONTH)), 2’0’);  
  298.          String ret = year + month + day + String.valueOf(ranNum);  
  299.            
  300.          return ret;  
  301.      }  
  302. }  

閲覧  |  コメント  |  目次

 
ヘルプ  |  ご利用規約  |  相互リンク  |  問合せ
リンクはご自由に、問合せはお気軽に
©2007 Uprush