CarrierWave Base64 图片上传

CarrierWave Base64 Image Upload

我正在将一个现有应用程序从 ASP.NET 转换为 Rails,但在上传 Base64 图像时碰壁了。我正在发送为 image 参数编码的图像 base64。我正在使用 CarrierWave 处理图像并将其存储在 S3 上。我已经尝试了所有我能找到的 Whosebug 文章,但都无济于事。

型号:

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

我最终解决了这个问题:

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] =  # "image/gif"
      uri[:encoder] =  # "base64"
      uri[:data] =  # data string
      uri[:extension] = .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