我正在尝试将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
答案 0 :(得分:2)
首先,鉴于此模型设计,您的Artwork模型未正确嵌入Upload
文档。它应该嵌入picture
和thumbnail
字段,如下所示:
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
您的picture
和thumbnail
字段将包含更新日期,文件名,文件日期等内容。
此外,您似乎正在尝试手动管理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#picture
和Artwork#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。