CarrierWave Base64图像上传

时间:2015-09-03 16:44:34

标签: ruby-on-rails image carrierwave

我正在将现有的应用程序从ASP.NET转换为Rails,并且正在使用Base64图像上传。我发送的图像base64编码为image参数。我正在使用CarrierWave处理和存储S3上的图像。我已经尝试了一些我找不到的stackoverflow文章。

型号:

class Image < ActiveRecord::Base
  self.table_name = "Images"
  self.primary_key = "ImageId"

  has_many :image_comments, foreign_key: :ImageId
  belongs_to :location, foreign_key: :LocationId
  belongs_to :company, foreign_key: :CompanyId

  accepts_nested_attributes_for :image_comments

  alias_attribute :id, :ImageId
  alias_attribute :active, :IsActive
  alias_attribute :filename, :Filename
  alias_attribute :date_uploaded, :DateUploaded
  alias_attribute :user_id, :UploadedById
  alias_attribute :notes, :Notes
  alias_attribute :location_id, :LocationId
  alias_attribute :lat, :Lat
  alias_attribute :lon, :Lon
  alias_attribute :company_id, :CompanyId
  alias_attribute :anonymous, :IsAnnonymousLocation
  alias_attribute :update_ticks, :UpdateTicks
  alias_attribute :url_large, :FullSizeUrl
  alias_attribute :url_medium, :WebSizeUrl
  alias_attribute :url_small, :MobileSizeUrl
  alias_attribute :image, :FullSizeUrl
  alias_attribute :date_received, :DateReceived

  mount_uploader :url_large, OriginalImageUploader
end

控制器

def create
  @image = @location.images.build(image_params)  

  if @image.save
    render json: @image, serializer: V1::ImageSerializer
  else
    api_error(status: 422, errors: @image.errors)
  end
end

上传

# encoding: utf-8
require 'image_io'
class OriginalImageUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  storage :fog

  before :cache, :convert_base64

  def convert_base64(file)
    filename = "test.jpg"
    content_type = "image/jpeg"
    decoded = Base64.decode64(file.read)
    file.tempfile.close!
    decoded = ImageIO.new(decoded)
    decoded.original_filename = filename
    decoded.content_type = content_type
    file.send :file=, decoded
  end

  # process :set_content_type
  # process :resize_to_fit => [1334, 1334]
  # process :quality => 75

  # def extension_white_list
  #   %w(jpg jpeg png)
  # end

end

的ImageIO

class ImageIO < StringIO
  attr_accessor :original_filename
  attr_accessor :content_type
end

1 个答案:

答案 0 :(得分:3)

我最终使用以下方法解决了问题:

def image_params
    img_params = params.require(:image).permit(:image, :filename, :date_uploaded, :lat, :lon, :update_ticks, image_comments: [:comment, :date_created, :user_id]).merge(user_id: current_user.id, company_id: current_user.company_id)
    img_params.merge(convert_data_uri_to_upload(img_params))
    img_params
  end

  def split_base64(uri_str)
    if uri_str.match(%r{^data:(.*?);(.*?),(.*)$})
      uri = Hash.new
      uri[:type] = $1 # "image/gif"
      uri[:encoder] = $2 # "base64"
      uri[:data] = $3 # data string
      uri[:extension] = $1.split('/')[1] # "gif"
      return uri
    else
      return nil
    end
  end

  def convert_data_uri_to_upload(obj_hash)
    if obj_hash[:image].try(:match, %r{^data:(.*?);(.*?),(.*)$})
      image_data = split_base64(obj_hash[:image])
      image_data_string = image_data[:data]
      image_data_binary = Base64.decode64(image_data_string)

      temp_img_file = Tempfile.new(obj_hash[:filename])
      temp_img_file.binmode
      temp_img_file << image_data_binary
      temp_img_file.rewind

      img_params = {:filename => obj_hash[:filename], :type => image_data[:type], :tempfile => temp_img_file}
      uploaded_file = ActionDispatch::Http::UploadedFile.new(img_params)

      obj_hash[:url_large] = uploaded_file
      obj_hash.delete(:image)
    end

    return obj_hash    
  end