Carrierwave + Mongoid + gridfs + Padrino管理员图片上传

时间:2014-06-13 11:12:43

标签: ruby mongoid carrierwave gridfs padrino

我正在尝试将carrierwave + mongoid + gridfs用于通过padrino管理员上传图像,然后在前端显示。粘合一切都不知所措。有人可以帮忙吗?

关注https://blog.engineyard.com/2011/a-gentle-introduction-to-carrierwave/https://github.com/carrierwaveuploader/carrierwave-mongoid

尝试通过图片上传保留“艺术作品”返回:

  

/ admin / artwork / update / 53a0eedcf2c7961066000002上的NoMethodError   #file文件的未定义方法` bson_dump ':   hash.rb location:阻塞在 bson_dump 行:15

mongofiles -d database list

返回空。

问题是:目前代码有什么问题?

上传者:https://github.com/bcsantos/debug/blob/master/lib/uploader.rb

class Uploader < CarrierWave::Uploader::Base

  ##
  # Image manipulator library:
  #
  include CarrierWave::RMagick
  # include CarrierWave::ImageScience
  # include CarrierWave::MiniMagick

  ##
  # Storage type
  #
  storage :grid_fs
  # configure do |config|
  #   config.fog_credentials = {
  #     :provider              => 'XXX',
  #     :aws_access_key_id     => 'YOUR_ACCESS_KEY',
  #     :aws_secret_access_key => 'YOUR_SECRET_KEY'
  #   }
  #   config.fog_directory = 'YOUR_BUCKET'
  # end
  # storage :fog

resize_to_limit(1024, 768)

  ## Manually set root
  def root; File.join(Padrino.root,"public/"); end

  ##
  # Directory where uploaded files will be stored (default is /public/uploads)
  #
  def store_dir
    'content'
  end

  ##
  # Directory where uploaded temp files will be stored (default is [root]/tmp)
  #
  def cache_dir
    Padrino.root("tmp")
  end

  ##
  # Default URL as a default if there hasn't been a file uploaded
  #
  # def default_url
  #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  # end

  ##
  # Process files as they are uploaded.
  #
  # process :resize_to_fit => [740, 580]

  ##
  # Create different versions of your uploaded files
  #
  # version :header do
  #   process :resize_to_fill => [940, 250]
  #   version :thumb do
  #     process :resize_to_fill => [230, 85]
  #   end
  # end
  ##
  # White list of extensions which are allowed to be uploaded:
  #
  def extension_white_list
    %w(jpg jpeg gif png)
  end

  ##
  # Override the filename of the uploaded files
  #
  # def filename
  #   "something.jpg" if original_filename
  # end
end

-----------

上传https://github.com/bcsantos/debug/blob/master/app/models/upload.rb

class Upload
  include Mongoid::Document
  include Mongoid::Timestamps # adds created_at and updated_at fields

  # field <name>, :type => <type>, :default => <value>
  field :file, :type => String
  field :created_at, :type => Time

  attr_accessible :upload

  mount_uploader :upload, Uploader


  # You can define indexes on documents using the index macro:
  # index :field <, :unique => true>

  # You can create a composite key in mongoid to replace the default id using the key macro:
  # key :field <, :another_field, :one_more ....>
end

-----------

模型我想将上传/图片与https://github.com/bcsantos/debug/blob/master/app/models/artwork.rb

相关联
class Artwork
  include Mongoid::Document
  include Mongoid::Timestamps # adds created_at and updated_at fields

  # field <name>, :type => <type>, :default => <value>
  field :name, :type => String
  field :year, :type => Integer
  field :author, :type => String
  field :rent_price, :type => String
  field :sale_price, :type => String
  field :medium, :type => String
  field :size, :type => String
  field :colour, :type => String

  field :picture, :type => Upload
  field :thumbnail, :type => Upload


  # You can define indexes on documents using the index macro:
  # index :field <, :unique => true>

  # You can create a composite key in mongoid to replace the default id using the key macro:
  # key :field <, :another_field, :one_more ....>
end

-----------

控制器从数据库中检索文件(感谢@Darío)

TourApart::App.controllers do

  get :gridfs, map: '/content/*' do
    gridfs_file = Mongoid::GridFS[params[:splat]]
    content_type gridfs_file.content_type
    gridfs_file.data
  end

  error Mongoid::Errors::MongoidError do
    halt 404, 'File not found'
  end

end

2 个答案:

答案 0 :(得分:2)

首先,鉴于此模型设计,您的Artwork模型未正确嵌入Upload文档。它应该嵌入picturethumbnail字段,如下所示:

class Artwork
  # ...
  embeds_one :picture, class_name: "Upload"
  embeds_one :thumbnail, class_name: "Upload"
  # ...
end

除此之外,我不明白为什么你首先要有Upload文件。鉴于您的设计,似乎没有必要。 Uploader包含您尝试在Upload模型中存储的所有信息。例如,您的Artwork模型可能只是这样(并且您可以将Upload模型全部转储):

class Artwork
  # ...
  mount_uploader :picture, Uploader
  mount_uploader :thumbnail, Uploader
  # ...
end

您的picturethumbnail字段将包含更新日期,文件名,文件日期等内容。

此外,您似乎正在尝试手动管理thumbnail。我认为缩略图是picture的较小版本。 Carrierwave也可以为您处理这个问题:

class Artwork
  # ...
  mount_uploader :picture, Uploader
  # ...
end

然后将这样的内容添加到您的Uploader

class Uploader < CarrierWave::Uploader::Base
  # ...
  version :thumbnail do
    process resize_to_fill: [160, 120]
  end
  # ...
end

这样,您将拥有两个不同版本的Artwork#pictureArtwork#picture_thumbnail访问者。

更多例子:

  • Artwork#picture.read - 获取图片数据
  • Artwork#picture.file - 获取图片文件
  • Artwork#picture_thumbnail.file - 获取缩略图版本的文件
  • Artwork#picture.file.content_type - 是的,content_type

最后,如果您使用的是carrierwave-mongoid,则无需直接在控制器中访问Mongoid::GridFS。查找图稿并访问picture字段。让GridFS留在幕后。

除此之外,我建议使用CarrierWave::MiniMagick而不是CarrierWave::RMagick。从长远来看,它只会让事情变得更容易,IMO,但它要求你在你的机器上安装了ImageMagick。

答案 1 :(得分:0)

这需要一段时间......帮助别人节省时间,这里有:

<强>的Gemfile

#...
gem 'mongoid', '~>3.0.0'
gem 'carrierwave-mongoid', :require => 'carrierwave/mongoid'
gem 'mini_magick', :require => 'mini_magick'
#...

<强> LIB / uploader.rb

class Uploader < CarrierWave::Uploader::Base

  include CarrierWave::MiniMagick

  storage :grid_fs

  ##
  # Directory where uploaded files will be stored (default is /public/uploads)
  #
  def store_dir
    '/content/images'
  end

  ##
  # Directory where uploaded temp files will be stored (default is [root]/tmp)
  #
  def cache_dir
    Padrino.root("/tmp")
  end

  def extension_white_list
    %w(jpg jpeg gif png)
  end

  ##
  # Override the filename of the uploaded files
  #
  # def filename
  #   "something.jpg" if original_filename
  # end
end

<强>模型

class Thing
  include Mongoid::Document
  include Mongoid::Timestamps

  field :name, :type => String
  field :year, :type => Integer
  #...

  mount_uploader :picture, Uploader
end

<强>控制器

YourApp::App.controllers :things do

  get :image, with: [:id], provides: ['.jpeg', '.jpg', '.png', '.gif'] do
    thing = Thing.find(params[:id])
    content_type thing.picture.content_type
    response.write(thing.picture.read)

  end

  error Mongoid::Errors::MongoidError do
    halt 404, 'File not found'
  end

end

查看(haml)

/...
%img{:src => url_for(:things, :image, thing.id)}/
/...

系统管理员/视图/东西/ _form.haml

/...
%fieldset.control-group{:class => error ? 'has-error' : ''}
  =f.label :picture, :class => 'control-label'
  .controls
    =f.file_field :picture, :class => 'form-control input-large input-with-feedback'
    %span.help-inline=error ? f.error_message_on(:picture, :class => 'file-error') : pat(:example)
/...

感谢@Ryan McGeary和@Darío。