`
woody_420420
  • 浏览: 41089 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Rails中如何更加优雅的处理文件上传

阅读更多

  通常,在rails中处理文件上传,我们会这么做,在view中生成相应html tag:

<input name="my_uploaded_file" type="file">

  然后,在controller中,我们可以通过params[:my_uploaded_file]得到上传文件,进行相应处理。
  假如,现在作为controller的开发人员,我不知道view开发人员将input的name设置成什么?那应该如何处理呢?可能这个例子有些极端,绝大部分时候不存在这个问题。那再假如,现在我们要利用rails实现一个api,该api的功能是实现文件上传,rails后台得到该文件,并进行处理。由于这是一个开放api,用户可能通过jsp,rails,php,甚至桌面程序等来访问我们的api,这个时候又该如何处理呢?(当然,你可以在api specification中定死,说,我的地盘我做主,你们要使用我的api上传文件,form-data的name必须是XXX!)
  在asp.net中倒是可以很简单的解决这个问题,我记得asp.net中的form提供了一个参数,开发人员可以直接访问该参数得到此form中所有上传的文件,而不必管name是什么。但是在rails中,似乎没有这一机制(如果是我疏忽,望知情同学告知!)。不过,现在稍加修改,rails也同样能象asp.net那样处理上传文件。
  首先,我先贴出解决方案,为方便起见,在environment.rb中加入如下代码:

module ActionController
  class AbstractRequest
    class << self
      alias_method :_original_read_multipart_, :read_multipart
      
      def read_multipart(body, boundary, content_length, env)
        params = _original_read_multipart_(body, boundary, content_length, env)
        file_data = params.values.dup.flatten.select do |form_data| 
          form_data.respond_to?(:original_path) && !form_data.original_path.blank?
        end
        params.merge!({"file_data[]" => file_data})
      end
      
      private :_original_read_multipart_, :read_multipart
    end
  end
end
 

  我先大致解释下这段代码:在view中的某个form中,当你加入{:multipart => true}参数,rails会调用AbstractRequest中的私有类方法read_multipart,得到form中所有的参数。所以,我的解决方案就是截获此方法,调用原始版本后,遍历form中的所有值,将所有上传的文件放到一个file_data中去,塞回params中。这样,在controller中,就可以通过params[:file_data]得到form中所有上传文件进行处理,而并不用理会input的name到底是什么。这样做,我们甚至可以处理这种情况:

<input name="same_name" type="file">
<input name="same_name" type="file">
 

  就算这两个input的名字相同,通过file_data,仍然可以得到两个文件。这样,controller得到上传文件的代码便独立了,和view没有任何关系,你爱咋写name都行。另外,这行代码有两个地方值得注意:

params.merge!({"file_data[]" => file_data})

  1. 关于key,不能想当然的用:file_data[]。因为rails内部处理参数的时候,调用了key.include?,所以,使用Symbol必然出错。
  2. [] 是必须的,否则rails不能将所有的上传文件塞到一个数组中去,这样,在controller中,你将只能通过file_data得到其中一个文件。
  另外,上述代码是基于rails 2.0.2。加入你目前正在使用rails 1.*。则可以使用如下代码实现相同的功能:

class CGI #:nodoc:
  module QueryExtension
    
    alias_method :_original_read_multipart_, :read_multipart
    def read_multipart(boundary, content_length)
      params = _original_read_multipart_(boundary, content_length)
      file_data = params.values.dup.flatten.select do |form_data| 
        form_data.respond_to?(:original_path) && !form_data.original_path.blank?
      end
      params.merge!({"file_data[]" => file_data})
    end

    private :_original_read_multipart_, :read_multipart
  end
end
 

  2008.7.19  22:22  星期六

分享到:
评论
2 楼 lijingtx 2015-12-07  
为什么我报错了。in `alias_method`:undefined method `read_multipart` for class `Class`(NameError)
1 楼 liuqiang 2008-07-20  
越发的感到:让rails处理图片简单一点吧!
http://www.iteye.com/topic/214661

相关推荐

    Ruby-CarrierWaveRubyWeb框架更优雅的解决方案文件上传

    CarrierWave - Rails、Sinatra和其它Ruby Web框架更优雅的解决方案文件上传

    JAVA上百实例源码以及开源项目

     数字证书:从文件中读取数字证书,生成文件输入流,输入文件为c:/mycert.cer,获取一个处理X.509证书的证书工厂…… Java+ajax写的登录实例 1个目标文件 内容索引:Java源码,初学实例,ajax,登录  一个Java+ajax写...

    基于MVC的JavaScript Web富应用开发

    , 揭开MVC的神秘面纱,教你如何设计合理的架构以及处理应用内部模块之间的依赖, 介绍模板引擎和数据绑定, 讲解远程数据加载、第二代Ajax以及跨域请求, 利用WebSockets和Node构建实时应用, 拖拽上传文件以及上传进度...

    JAVA上百实例源码以及开源项目源代码

     数字证书:从文件中读取数字证书,生成文件输入流,输入文件为c:/mycert.cer,获取一个处理X.509证书的证书工厂…… Java+ajax写的登录实例 1个目标文件 内容索引:Java源码,初学实例,ajax,登录  一个Java+ajax写...

    java开源包1

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    java开源包11

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    java开源包2

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    java开源包3

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    java开源包6

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    java开源包5

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    java开源包10

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    java开源包4

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    java开源包8

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    java开源包7

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    java开源包9

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    java开源包101

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

    Java资源包01

    Java文件上传组件 COS FAT文件系统读写类库 fat32-lib fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的...

Global site tag (gtag.js) - Google Analytics