Gem gem 'carrierwave'简易实用介绍

jesktop · 发布于 2012年08月17日 · 最后由 torvaldsdb 回复于 2017年01月20日 · 12053 次阅读
1164

gem 'carrierwave'

Carrierwave的主要功能是用于上传文件或者图片的Gem,功能非常强大。我在这里做一个非常简单的使用步骤,并不对Carrierwave做详细的介绍。


创建uploader

$ rails g uploader Photo
   create  app/uploaders/photo_uploader.rb

uploader这个文件非常重要,carrierwave许多功能都将在photo_uploader.rb里实现。

创建字段存储文件信息

$ rails g migration AddPhotoToUsers photo:string 
      invoke  active_record
      create    db/migrate/20120816163431_add_photo_to_users.rb

photo字段使用与存储上传文件的地址字段。 然后在User的model中加入调用carrierwave的信息:

class User < ActiveRecord::Base
  mount_uploader :photo, PhotoUploader

这样Model和数据库就可以处理好上传上来的文件了。 接下来需要处理一下View,在正常的new下添加上传的按钮。

Views中添加相关设置

<%= form_for @user, :html => {:multipart => true} do |f| %>
  <p>
    <label>My Photo</label>
    <%= f.file_field :photo %>
    <%= f.hidden_field :photo_cache %>
  </p>
<% end %>

关键在form_for中添加:html => {:multipart => true},就可以使用上传功能了.

使用只需要在需要的地方添加<%= image_tag(@user.photo_url) %>就可以了。 这样,就完成了上传功能了。下面对上传图片的一些特别事项,做一些简单的描述。


使用RMagick生成多个图片版本

这里需要使用到另外一个Gem,名字为RMagick。 如果在安装gem 'rmagick'的过程中出现“Can't find Magick-config”的错误,以下链接就有处理这个问题的方法。 http://stackoverflow.com/questions/5201689/rmagick-gem-install-cant-find-magick-config 安装完RMagick后,就可以设置版本信息。 打开class PhotoUploader,然后添加RMagick支持:

include CarrierWave::RMagick

注意:由于RMagick会导致内存泄露,建议使用Mini_Magick,gem "mini_magick",使用方法基本和RMagick差不多

include CarrierWave::MiniMagick

设置版本信息:

process :resize_to_fit => [800, 800]       #图片大小不超过800*800

version :thumb do                                 #版本名为thumb
  process :resize_to_fill => [200,200]      #想图片处理成200*200大小
end
  • 不设置vesrion则为默认版本,既使用方法为<%= image_tag(@user.photo_url) %>
  • 而thumb版本的使用方法也很简单,<%= image_tag(@user.photo_url(:thumb)) %>也就是添加thumb参数就可以了,版本号为什么就添加什么。非常方便。 # 限制文件上传格式 # 添加如下代码就可以让用户只上传图片文件了。 ruby class PhotoUploader < CarrierWave::Uploader::Base def extension_white_list %w(jpg jpeg gif png) end end * * * 这是个非常简单的教程,也谈不上是教程,也就是说明书而已,因为在github上,我说写的上面的写的非常清楚。我就是抽出一部分我比较常用的内容写了下来,这样就可以直接按照上面的流程下来,完成需要的部分功能。 如需要了解更加详细的内容,可以登陆:https://github.com/jnicklas/carrierwave
共收到 25 条回复
96

如何实现图片预览和用户自定义剪裁呢?可否给个思路 谢谢楼主了

2394

楼主,这句话的作用是什么呢? <%= f.hidden_field :photo_cache %>

475

顺便问一下楼主photo_cache是什么

395

楼主,请使用Mini_Magick替换RMagick,那个有内存泄漏问题

395

#1楼 @karma 剪裁预览用Jcrop

1353

预览和用户自定义剪裁都是用js实现的

96

@fresh_fish @metal 谢谢,我去了解一下jcrop! 还有一个问题,我也听说过RMagick有内存泄露的问题所以我平时使用的时候都是使用的Mini_Magick,但是Mini_Magick只能处理已存在的图片吗?我在做一个验证码生成的gem时候遇到了这样的问题: 我希望直接将内存中的图片(验证码)输出给用户,而不写入到服务器上,RMagick好像可以实现,Mini_Magick要怎么做呢? 如果做验证码的话,是一次性生成还是,然后随机抽取给用户;还是用户请求的时候再动态生成比较好呢?效率上,和安全上那种好一些呢? 如果一次性生成的话,有必要对这些图片cache吗?

最后,如何模拟大量的请求呢?对于商业的项目在开发时有没有特别要注意的地方,我问的比较笼统,因为自己对这方面的积累几乎完全空白,所以有没有相关的书或者rails的开源项目推荐,最好能有一些书,因为看项目的话,很多时候不能知其所以然,我希望能补充一些理论方面知识?

谢谢了!

395

#8楼 @karma Mini_Magick 可以直接调用 ImageMagick 的命令,所以RMagick 能做的 Mini_Magick 一样能做,但是你得先了解一下 ImageMagick 的 命令。 模拟大量请求 可以用Apache ab 模拟并发吧

1164

#2楼 @tomwey #4楼 @metal 官方解释是:Often you'll notice that uploaded files disappear when a validation fails. CarrierWave has a feature that makes it easy to remember the uploaded file even in that case. 实际上使用的效果是这样的,就是当你选择了文件之后,然后把你的文件仿如cache中。 例如:如果你的表单有name,photo(上传图片),而表单验证的要求是,必须name是不可以空白或者带有文字,然后这时候,你填写了name为123,而photo也上传了图片,然后提交,却无法通过验证。这个适合cache的作用就出来了。 当有这行代码<%= f.hidden_field :photo_cache %>则在验证返回之后,你不需要在重新上传图片,只需要把name改为abc就可以成功的提交表单了。 而如果没有的话,就会因为图片没有存在cache中也没有上传到服务器里,所以当name的验证失败返回后,就需要你重新在上传一次图片了。

1164

#5楼 @fresh_fish Thanks,一直还不知道RMagick有这样的问题。

1924

#1楼 @karma 自定义剪切仅仅靠这些个gem 是不行的,js 有很多自定义剪切图片的插件,google一下很多的,具体怎么处理可见其demo

1267

js剪切图片???貌似常用的是js获取选择的两个点的元素坐标,把坐标和图片信息发到服务器,然后再服务器用Mini_Magick来剪吧。

不过html5或许有支持,这个偶不知道。

2099

为什么我文件裁剪,最后没保存进去!

class AvatarUploader < CarrierWave::Uploader::Base
  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  include CarrierWave::MiniMagick

  # Choose what kind of storage to use for this uploader:
  storage :file
  # storage :upyun

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    # "uploads/#{model.class.to_s.underscore}/#{model.id}"
    "#{model.class.to_s.underscore}/#{mounted_as}"
  end

  # Provide a default URL as a default if there hasn't been a file uploaded:
  def default_url
    _filename = ["default_avatar", version_name, "png"].join(".")
    # For Rails 3.1+ asset pipeline compatibility:
    return ActionController::Base.helpers.asset_path("fallback/#{_filename}")

    "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  end

  # Process files as they are uploaded:
  # process :scale => [200, 300]
  #
  # def scale(width, height)
  #   # do something
  # end

  # Create different versions of your uploaded files:

  process :cropper

  version :thumb do
    process resize_to_fit: [50, 50]
  end

  version :mid do
    process resize_to_fit: [180, 180]
  end

  version :large do
    process resize_to_fit: [300, 300]
  end

  def cropper
    if model.crop_x.present?
      manipulate! do |img|
        x = model.crop_x
        y = model.crop_y
        w = model.crop_w
        h = model.crop_h
        img.crop "#{w}x#{h}+#{x}+#{y}"
      end
    end
  end

  # Add a white list of extensions which are allowed to be uploaded.
  # For images you might use something like this:
  def extension_white_list
    %w(jpg jpeg gif png)
  end

  # Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  def filename
    "#{secure_token}.#{file.extension}" if original_filename.present?
  end

  protected
  def secure_token(length=16)
    var = :"@#{mounted_as}_secure_token"
    model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.hex(length/2))
  end
end

D09c5b

怎么修改图片的名字,名字是uuid自动生成的。

10603

@JeskTop 楼主你好,请问下你是怎么实现多文件上传的?因数用carrierwave要数据库支持array或者json数据类型,但mysql是不支持的,文档如下:

Add a column which can store an array. This could be an array column or a JSON column for example. Your choice depends on what your database supports. For example, create a migration like this:

rails g migration add_avatars_to_users avatars:json rake db:migrate Open your model file and mount the uploader:

class User < ActiveRecord::Base mount_uploaders :avatars, AvatarUploader end Make sure your file input fields are set up as multiple file fields. For example in Rails you'll want to do something like this:

<%= form.file_field :files, multiple: true %> 多谢

1164

#17楼 @luolinae86 不好意思,目前我也还没有做过多图上传的。

15420

#16楼 @liker CarrierWave 里 有个自带的 filename 方法,可以定义存到文件夹里面 文件的名字。文件的原来的名字是original_filename

96

#17楼 @luolinae86 同求怎样实现多文件上传,数据也是MySQL

10603

@15731118085 多文件及图片上传的,我最终是用的jquery文件异步上传插件,非常好用,也没用阻塞服务,请参考下面的例子

https://blueimp.github.io/jQuery-File-Upload/

96

你好,我在显示图片时遇到如下问题: wrong number of arguments (given 1, expected 0)

Extracted source (around line #18):

<%= @course.course_introduction %> 18 <%= image_tag(@course.avatar(:lb)) %>

Rails.root: /home/stormand/RubymineProjects/CourseSelect Application Trace | Framework Trace | Full Trace

app/views/courses/detail.erb:18:in `app_views_courses_detail_erb_3528013227028476933_69855157661360'

Request

Parameters:

{"id"=>"1"}

为什么添加(:lb)版本号后就会报错啊?如果删去(:lb)就没有问题。 uploader中也定义了版本

1164

#22楼 @stormand 这个4年前的文章了啊,现在gem更新了什么,有什么改动,你要对照文档去操作比较好。

19780

<%= f.hidden_field :photo_cache %>I tried, but it didn't work!

19780

#22楼 @stormand 如果是版本你的image_tag(@course.avatar(:lb))有点问题吧, image_tag尽管提到

Returns an HTML image tag for the source. The source can be a full path or a file.

但是carrierwave的版本只支持 full path, 你可以尝试image_tag(@course.avatar_url(:lb))或者image_tag(@course.avatar.thumb.url)

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册