rails:上传图片到服务器和upyun

发表于:,更新于:,By Sally
大纲
  1. 1. app应用图片上传
    1. 1.1. 1. 将图片上传到服务器
    2. 1.2. 2. 将本地已有的图片对象,上传到upyun
    3. 1.3. 3. 在web应用中,将图片上传到upyun
  2. 2. 借助gem将图片上传到服务器以及upyun
  3. 3. github原文

app应用图片上传

1. 将图片上传到服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def save_img_to_server
# 拿到传递过来的图片对象
img_url = params[:file1].original_filename
public_root_dir = "/opt/app/youjia_web/current/public"
img_dir = "/uploads/images/#{decoratingcase.id}/"
public_dir = public_root_dir + img_dir
# 确保这个文件夹存在
`mkdir -p #{public_dir}`
img_save_path = File.join(public_dir, img_url)
File.open(img_save_path, "wb") { |f| f.write(img_url.read) }
# 保存到数据库
decoratingcaseimage = DecoratingCaseImage.new({
:img_url => img_url,
});
decoratingcaseimage.save!
end

2. 将本地已有的图片对象,上传到upyun

  • 需要使用rubygem:upyun
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 假设放到copy_all_files_to_upyun.rb文件中
require 'upyun'
# upyun上空间的名称, 操作员名称, 操作员密码
upyun = Upyun::Rest.new('your_bucket', 'operator_name', 'password')
# 本地路径: ./folder/1/2/3.jpg, 那么,上传到 远程后,应该是: /1/2/3.jpg, 域名/1/2/3.jpg
# 执行这个脚本的要求是:
# 1. cd 到 目标文件夹的同级目录,例如: projectName/public
# 2. 目标文件夹(例如: files ). 直接运行
root ='/opt/app/projectdemo/shared/public'
folder = '/uploads'
files_and_folders = `find #{root + folder}`

files_and_folders.split("\n").select{ |entity|
entity.include?(".")
}.each { |file|
remote_file_path = file.sub(root, '')
puts "=remote_file_path: #{remote_file_path.inspect}"
puts "= local file: #{file.inspect}"
puts upyun.put(remote_file_path, File.new(file))
}

3. 在web应用中,将图片上传到upyun

  • 还是需要rubygem:upyun

  • 首先,需要有一个图片对象的model,字段根据情况书写

  • 其次,视图层.html.erb文件

1
2
3
4
5
6
<%= form_for @upload, :html => {multipart: true}  do |f| %>
<%= file_field_tag :file %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>

  • 最后,控制器action动作, ps:再自我提醒一次:这里最好搞懂每个action的执行作用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class UploadsController < ApplicationController
before_action :set_upload, only: [:show, :edit, :update, :destroy]
def new
@upload = Upload.new
respond_with(@upload)
end

require 'upyun'
def create
@upload = Upload.new(upload_params)
@upload.save

bucket = 'upyun空间的名称'
operator = '操作员名称'
password = '操作员密码$'
upload_file = params[:file]
upyun = Upyun::Rest.new(bucket, operator, password)
remote_file = "/image/#{@upload.id}/#{upload_file.original_filename}"
response = upyun.put remote_file, upload_file.read
render :json => {
:response => response,
# upyun给的默认域名或者自己设置的二级域名
:url => "http:/xxxx.b0.upaiyun.com/#{remote_file}"
}
end
end

借助gem将图片上传到服务器以及upyun

  • upyuncarrierwave一起使用

  • 在gemfile中添加如下gem:

1
2
gem 'carrierwave', '0.9.0'
gem 'carrierwave-upyun'
  • bundle install

  • 在config/initializers/cacrrierwave.rb文件中,增加如下代码, ps:此文件需要自己手动创建

1
2
3
4
5
6
7
CarrierWave.configure do |config|
config.storage = :upyun
config.upyun_username = "xxxxxx" # 操作员名称
config.upyun_password = 'xxxxxx' # 操作员密码
config.upyun_bucket = "my_bucket" # upyun空间名称
config.upyun_bucket_host = "http://my_bucket.files.example.com"
end
  • 在对应的uploader中,使用storage:upyun
  • 也就是生成的这个ImageUploader文件中
1
bundle exec rails generate uploader ImageUploader
1
2
3
4
class AvatarUploader < CarrierWave::Uploader::Base
storage :upyun
# storage :file
end
  • 最后,还要在存储改图片的model中添加这么一句
1
2
3
4
class DecoratingCaseImage < ActiveRecord::Base
# 存储图片的字段, 上一步生成的uploader文件名称
mount_uploader :img_url, ImageUploaderUploader
end
  • 最最后,就是执行save动作了,这里应该注意,其实字段里保存的是图片的完整路径,并不行数据库显示的那样,仅仅是图片的名字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 假设,客户端传过来多张图片, 我们将图片实体存放在image_urls中
image_urls = (1..params[:images_count].to_i).map {|i|
params["file#{i}"]
}

# 然后,将每一个图片实体存放到upyun上
image_urls.each do |image_url|
puts "==== #{image_url.inspect}" #这样就可以看到图片对象所包含的所有信息
puts "=== uploading: #{image_url} to upyun" #这里拿到的就是图片在upyun上的地址
image = DecoratingCaseImage.new # 创建实例,保存
image.img_url = image_url
image.decorating_case_detail_id = decoratingcasedetail.id
image.save
end
  • 注: 使用这种方式存储图片,根本不需要考虑图片存储路径的问题,在本地数据库看起来存储的是图片的名称,实际上获得该字段的属性值,可以直接访问upyun上的图片对象
  • 注: upyun获取缩略图的方式: http://图片地址.jpg!40*40 即显示40*40大小的图片

github原文