让Rails版的FCKEditor支持动态设置上传目录

一个多用户的系统,上传图像文件等,希望不同用户的图像上传到它专有的目录里。我最初查到在PHP版的FCKEditor是通过设 置$Config('UserFilesPath')来实现,但Rails版的FCKEditor没有此项设置(搜索UserFilesPath关键字后 做出此判断)。接着,我查看了FCKEditor关键的fckeditor_controller.rb的源代码,似乎它并不支持此项设置。再看 javaeye是怎么用FCKEditor的,发现它放弃了FCKEditor的上传功能。google了半天,除了那些转来转去的相同内容的帖子之外 (搞不懂有了google之后,怎么还会有人费劲去转帖别人的文章),一点营养也没有。在JavaEye发了个求助帖,没人理 :-( 。 传说中高手云集的JavaEye,其Rails版块真是冷清,给人阴飕飕的感觉。没办法,自己改源代码吧。

文/陈刚 www.chengang.com.cn 转载请保留出处

1.修改fckeditor_controller.rb,把它那几个private方法修改如下:

  
  
private
  def current_directory_path
    base_dir 
=   " #{RAILS_ROOT}/public "

    #TODO 在创建用户时,就建立好目录。这时可以去掉这部份代码,提高运行效率。
    (
" #{params[:uploaded]||UPLOADED}/#{params[:Type]} " ).split( ' / ' ).each  do   | s |
    next 
if  s == ''
        base_dir 
+=   ' / '   +  s
        Dir.mkdir(base_dir,
0775 ) unless File.exists ? (base_dir)
    end
    
    check_path(
" #{base_dir}#{params[:CurrentFolder]} " )
  end
  
  def upload_directory_path
    uploaded 
=  @request.relative_url_root.to_s + " #{params[:uploaded]||UPLOADED}/#{params[:Type]} "
    
" #{uploaded}#{params[:CurrentFolder]} "
  end
  
  def check_file(file)
    # check that the file is a tempfile object
    unless 
" #{file.class} "   ==   " Tempfile "   ||   " #{file.class} "   ==   " StringIO "
      @errorNumber 
=   403
      
throw  Exception. new
    end
    file
  end
  
  def check_path(path)
    exp_path 
=  File.expand_path path
    
if  exp_path  !~   % r[ ^ #{File.expand_path(RAILS_ROOT)} / public #{params[:uploaded] || UPLOADED}]
      @errorNumber 
=   403
      
throw  Exception. new
    end
    path
  end


另外,它前面的常量UPLOADED_ROOT也没用了,可以删掉。


2. 在上面的代码中params[:uploaded] 是关键,它就是我们动态定义的上传目录。该值来自于FCKEditor的一些html页面,它是通过get参数传入的。修改browser.html文件 (如下粗体部份),在它的url请求中把我们定义目录加入到get参数列中,这样它就可以传到fckeditor_controller.rb里了


var sServerPath 
=  GetUrlParam(  ' ServerPath '  ) ;
if  ( sServerPath.length  >   0  )
    oConnector.ConnectorUrl 
+=   ' ServerPath= '   +  escape( sServerPath )  +   ' & '  ;

var sUploaded 
= GetUrlParam( 'uploaded' ) ;
if ( sUploaded.length > 0 )
    oConnector.ConnectorUrl 
+= 'uploaded=' + escape( sUploaded ) + '&'
 ;

oConnector.ResourceType        
=  GetUrlParam(  ' Type '  ) ;
oConnector.ShowAllTypes        
=  ( oConnector.ResourceType.length  ==   0  ) ;


3.  上面
的GetUrlParam( 'uploaded' ) 的值来自于fckcustom.js。修改fckcustom.js(如下粗体部份),把uploaded加入到get参数列中。

//  CHANGE FOR APPS HOSTED IN SUBDIRECTORY
FCKRelativePath 
=   '' ;

//  DON ' T CHANGE THESE
FCKConfig.LinkBrowserURL  =  FCKConfig.BasePath  +   ' filemanager/browser/default/browser.html?Connector= ' + FCKRelativePath + ' /fckeditor/command ' ;
FCKConfig.ImageBrowserURL 
=  FCKConfig.BasePath  +   ' filemanager/browser/default/browser.html?uploaded= '+FCKConfig.uploaded+' &Type=Image&Connector= ' + FCKRelativePath + ' /fckeditor/command ' ;
FCKConfig.FlashBrowserURL 
=  FCKConfig.BasePath  +   ' filemanager/browser/default/browser.html?uploaded= '+FCKConfig.uploaded+' &Type=Flash&Connector= ' + FCKRelativePath + ' /fckeditor/command ' ;

FCKConfig.LinkUploadURL 
=  FCKRelativePath + ' /fckeditor/upload ' ;
FCKConfig.ImageUploadURL 
=  FCKRelativePath + ' /fckeditor/upload?Type=Image&uploaded= '+ FCKConfig.uploaded;
FCKConfig.FlashUploadURL 
=  FCKRelativePath + ' /fckeditor/upload?Type=Flash&uploaded= '+ FCKConfig.uploaded;
FCKConfig.AllowQueryStringDebug 
=  false;
FCKConfig.SpellChecker 
=   ' SpellerPages ' ;

//  ONLY CHANGE BELOW HERE
FCKConfig.SkinPath 
=  FCKConfig.BasePath  +   ' skins/silver/ ' ;
FCKConfig.AutoDetectLanguage 
=  false ;
FCKConfig.DefaultLanguage 
=   ' zh-cn '  ;
FCKConfig.FontNames 
=   ' 微软雅黑;宋体;黑体;隶书;楷体_GB2312;Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana '  ;

FCKConfig.ToolbarSets[
" Simple " =  [
    [
' Source ' , ' - ' , ' FitWindow ' , ' Preview ' , ' - ' , ' Templates ' ],
    [
' PasteText ' , ' PasteWord ' ],
    [
' Undo ' , ' Redo ' , ' Find ' , ' Replace ' ],
    
' / ' ,
    [
' RemoveFormat ' , ' Bold ' , ' Italic ' , ' Underline ' , ' StrikeThrough ' ],
    [
' OrderedList ' , ' UnorderedList ' , ' Outdent ' , ' Indent ' ],
    [
' JustifyLeft ' , ' JustifyCenter ' , ' JustifyRight ' , ' JustifyFull ' ],
        [
' TextColor ' , ' BGColor ' ],
    [
' Link ' , ' Unlink ' , ' Anchor ' ],
    [
' Image ' , ' Flash ' , ' Table ' , ' Rule ' , ' Smiley ' ],
    
' / ' ,
    [
' Style ' , ' FontFormat ' , ' FontName ' , ' FontSize ' ]
] ;


4. 上面FCKConfig.uploaded的值来自于fckeditor.rb。在fckeditor.rb中加入一句(如下粗体所示)。

      javascript_tag(  " var oFCKeditor = new FCKeditor('#{id}', '#{width}', '#{height}', '#{toolbarSet}');\n " +
                      
" oFCKeditor.BasePath = \ " # {base_path}\"\n"+
                       " oFCKeditor.Config['CustomConfigurationsPath'] = 'http://www.cnblogs.com/fckcustom.js';\n " +
                      
"oFCKeditor.Config['uploaded'] = '#{options[:path]}';\n"+
                      
" oFCKeditor.ReplaceTextarea();\n " )                         


5.不 过上面oFCKeditor.Config['uploaded']的值要传到fckcustom.js的FCKConfig.uploaded里,还需 要修改fckeditorcode_gecko.js和fckeditorcode_ie.js(这两个文件对javascript进行了压缩处理,修改 起来较难操作)。我是参考了oFCKeditor.Config['CustomConfigurationsPath'] 这个参数的载入实现,才找到这种鸟不生蛋的地方。搜索这两个文件的关键字CustomConfigurationsPath,找到如下一行,然后加入一个else if判断(如下粗体所示)。

if  (D == ' CustomConfigurationsPath ' ) FCKConfig[D] = E; else if (D=='uploaded') FCKConfig[D]=E; else   if  (E.toLowerCase() == " true " this .PageConfig[D] = true ;



6.最后在fckeditor.rb里的#{options[:path]}来自于我们前台的view了。如下粗体所示,把标准的fckeditor_textarea新增加了一个参数,其中params[:user_id]是把用户的ID值做为目录名。这样就实现了动态改变FCKEditor的上传目录。

<%= fckeditor_textarea(:topic, :content, :ajax  =>   true , :toolbarSet  =>   ' Simple ' , :height  =>   ' 400px ' ,  :path  =>   " /uploads/#{params[:user_id]} " %>



修 改完后需要重启WEB服务,最后别忘记把public/javascripts/fckeditor和vendor/plugins/fckeditor /public/javascripts同步一下,原因见http://www.blogjava.net/chengang/archive/2007 /09/24/147867.html



转自: http://www.blogjava.net/chengang/archive/2007/09/26/148114.html

你可能感兴趣的:(fckeditor)