rails提供了一个gem来快速使用七牛,在Gemfile文件中添加
gem 'carrierwave', '~> 1.0.0'
gem 'carrierwave-qiniu', '~> 1.1.0'
gem 'figaro'
在model/image.rb
# == Schema Information
#
# Table name: images
#
# id :integer not null, primary key
# md5 :string
# file_size :integer
# filename :string
# image :string
# created_at :datetime not null
# updated_at :datetime not null
# url :string
#
class Image < ActiveRecord::Base
has_many :crowdfunding_image
mount_uploader :image, ImageUploader
before_save :mark_image_changed
after_save :save_url
# 标记文件是否改变,用于在 after_save 中使用
def mark_image_changed
@_image_changed = self.image_changed?
end
# 图片上传后,保存完成 URL
# 依赖于在图片上传完成后触发,因此只有图片上传后 self.image.url 才会返回 URL 而非本地临时文件路径
def save_url
# 只有图片上传后才保存,避免更新记录但未重新上传文件时执行
if @_image_changed
url = self.image.url
if url.blank? || url !~ %r{^https?://}
self.errors.add :base, '图片 URL 错误'
raise ActiveRecord::Rollback
else
# update_columns 会跳过 callback(也不会自动更新 updated_at),避免死循环
self.update_columns url: url, updated_at: Time.current
@_image_changed = false
end
end
end
# 覆盖 CarrierWave 增加的辅助函数
def image_url
self.url
end
end
model/crowdfunding_image.rb
class CrowdfundingImage < ActiveRecord::Base
belongs_to :image
attr_accessor :image_file
attr_accessor :image_file2
before_create :take_care_of_image
belongs_to :crowdfunding
# mount_uploader :image, ImageUploader
private
def take_care_of_image
return unless image_file = self.image_file
file_path = image_file.tempfile.path
md5 = Digest::MD5.file(file_path).to_s
if found= Image.find_by(md5: md5)
self.image = found
else
data = {
md5: md5,
filename: image_file.original_filename,
file_size: image_file.size,
image: image_file
}
self.image = Image.create(data)
end
end
end
model/crowdfunding.rb
class Crowdfunding < ActiveRecord::Base
has_many :crowdfunding_images, dependent: :destroy
attr_accessor :imagefile
end
config/application.yml
#输入七牛的相关的
development:
qiniu_access_key: ...
qiniu_secret_key: ...
qiniu_bucket_domain: ....
qiniu_bucket: *****
config/initializers/carrierwave.rb
::CarrierWave.configure do |config|
config.storage = :qiniu
config.qiniu_access_key = ENV['qiniu_access_key']
config.qiniu_secret_key = ENV['qiniu_secret_key']
config.qiniu_bucket = ENV['qiniu_bucket']
config.qiniu_bucket_domain = ENV['qiniu_bucket_domain']
config.qiniu_bucket_private = false
config.qiniu_block_size = 4*1024*1024
config.qiniu_protocol = "http"
#config.qiniu_up_host = 'http://up.qiniug.com' #七牛上传海外服务器,国内使用可以不要这行配置
end
app/uploaders/image_uploader.rb
class ImageUploader < 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 :fog
storage :qiniu
# 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
'resource'
end
# Provide a default URL as a default if there hasn't been a file uploaded:
# def default_url
# # For Rails 3.1+ asset pipeline compatibility:
# # ActionController::Base.helpers.asset_path(
# # "fallback/" + [version_name, "default.png"].compact.join('_')
# # )
#
# "/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:
# version :thumb do
# process resize_to_fit: [50, 50]
# end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
# def extension_whitelist
# %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
model.md5
end
end
app/views/crowdfunding/_form.html.erb
<div class="form-group required">
<%= f.label '产品主图' %><br>
<% url = image.find_by(crowdfunding_image_category_id: 1).try(:image).try(:image).try(:url) %>
<% if url.blank? %>
<img id="pic" src="<%= image_url('add.png') %>" width="200" height="200">
<% else %>
<img id="pic" src="<%= url %>" width="200" height="200">
<% end %>
<%= f.file_field :imagefile, class: 'form-control', id: "upload",style: "display: none" %>
</div>
<script>
//上传前的本地预览图片
$(function() {
$("#pic").click(function () {
$("#upload").click();
$("#upload").on("change",function(){
var objUrl = getObjectURL(this.files[0]) ;
if (objUrl) {
$("#pic").attr("src", objUrl) ;
};
});
});
});
</script>
app/controller/crowdfunding_controller.rb
def create
@crowdfunding = Crowdfunding.new(crowdfunding_params)
respond_to do |format|
if @crowdfunding.save
Crowdfunding.transaction do
@cro = CrowdfundingImage.new(image_file: params[:crowdfunding][:imagefile], crowdfunding_id: @crowdfunding.id, crowdfunding_image_category_id: 1)
@cro2 = CrowdfundingImage.new(image_file: params[:crowdfunding][:imagefile2], crowdfunding_id: @crowdfunding.id, crowdfunding_image_category_id: 2)
if @cro.save & @cro2.save
format.html { redirect_to @crowdfunding, notice: 'Crowdfunding was successfully created.' }
format.json { render :show, status: :created, location: @crowdfunding }
else
format.html { render :new }
format.json { render json: @crowdfunding.errors, status: :unprocessable_entity }
end
end
format.html { redirect_to @crowdfunding, notice: 'Crowdfunding was successfully created.' }
format.json { render :show, status: :created, location: @crowdfunding }
else
format.html { render :new }
format.json { render json: @crowdfunding.errors, status: :unprocessable_entity }
end
end
end