使用纸片夹保存从API获取的Base64图像

12

我有一个Photo模型,其中包含一个图像属性。该图像包含从API获取的base64字符串。我需要运行一个after_create回调函数,并且我想我可以在回调函数中使用Paperclip将图像保存到磁盘上,因为这样可以节省实现公共文件夹中的文件夹结构和生成缩略图的工作量。是否有简单的方法可以实现这一点?

5个回答

19
为了回答我自己的问题,这就是我想到的:

class Photo < ActiveRecord::Base

  before_validation :set_image

  has_attached_file :image, styles: { thumb: "x100>" }
  validates_attachment :image, presence: true, content_type: { content_type: ["image/jpeg", "image/jpg"] }, size: { in: 0..10.megabytes }

  def set_image
    StringIO.open(Base64.decode64(image_json)) do |data|
      data.class.class_eval { attr_accessor :original_filename, :content_type }
      data.original_filename = "file.jpg"
      data.content_type = "image/jpeg"
      self.image = data
    end
  end

end

image_json是一个文本字段,包含实际的base64编码图像(仅为数据部分,例如"/9j/4AAQSkZJRg...")


你好,从视图中,你是否将编码后的字符串作为隐藏字段传递给控制器?然后在控制器中,你做了什么操作? - Santino 'Sonny' Corleone
没有什么特别的,只是像Photo.create!(image_json:i)这样的东西,其中i是来自params哈希中包含base64字符串的数据。 - Marek Příhoda
如何从控制器编写它...它给我一个未定义的image_json方法。 - user569445
1
@user569445 在你的模型中添加 attr_accessor :image_json。 - Beder Acosta Borges
将'data.content_type'赋值给'self.image=data'并不会反映出来。Paperclip会找到传递的base64的内容类型,而不管'data.content_type'的内容是什么。因此,验证content_type时会出现问题。如何解决这个问题?! - Rooby Doo

6
你的`set_image`应该长成这个样子。
    def set_image        
       self.update({image_attr: "data:image/jpeg;base64," + image_json[PATH_TO_BASE64_DATA]})
    end

3
从Paperclip 5.2开始,您需要为Paperclip注册DataUriAdapter来处理base64图像。
在config/initializers/paperclip中输入: Paperclip::DataUriAdapter.register 然后,正如@eldi所说,您可以执行以下操作:
Photo.new(
   image:  "data:image/jpeg;base64,#{image_json}",
   image_file_name: 'file.jpg' # this way you can provide file_name
 )

(请查看Paperclip发布说明,点击这里)

我尝试了这个,但它显示:ActiveModel::UnknownAttributeError (unknown attribute 'image' for Image.): - jywarren
Processing by ImagesController#create as */* Parameters: {"authenticity_token"=>"XXX", "data"=>"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAQABADASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAf/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAABgj/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCdABykX//Z"} - jywarren
我已经添加了 Paperclip::DataUriAdapter.register -- 有什么想法吗? Paperclip 5.2。谢谢! - jywarren
@image = Image.new(uid: current_user.uid, image: params[:data], image_file_name: 'dataurl') - jywarren
抱歉@jywarren,让你久等了。看起来你没有使用正确的附件属性名称。 在你的“Image”模型中,你挂载paperclip时,附加文件的名称是什么?在下面的示例中,它是“avatar”。在我的示例中,它是“image”: has_attached_file:avatar 无论它是什么,那就是你需要用来提交图像数据的属性。 - Ollie H-M
哦,太棒了,发现得好!在我的项目中,属性是photo而不是image。更改并推送新的提交 - 希望它能正常工作:https://github.com/publiclab/plots2/pull/3619 - jywarren

3

至少在Paperclip 5中,它可以直接使用。您需要提供带有格式的base64字符串:data:image/jpeg;base64,#{base64_encoded_file}

对于您的模型,它将是:

Photo.new(
   image:  "data:image/jpeg;base64,#{image_json}",
   image_file_name: 'file.jpg' # this way you can provide file_name
 )

另外,在您的控制器中,您不需要更改任何内容:-)(也许您想在params中接受:image_file_name


带有点的内容类型在4.2左右得到了修复,早期版本也支持base64适配器,但仅适用于简单的内容类型(修复是正则表达式替换)。 - Vasfed

1
require 'RMagick'
data = params[:image_text]# code like this  data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABPUAAAI9CAYAAABSTE0XAAAgAElEQVR4Xuy9SXPjytKm6ZwnUbNyHs7Jc7/VV9bW1WXWi9q
image_data = Base64.decode64(data['data:image/png;base64,'.length .. -1])
new_file=File.new("somefilename.png", 'wb')
new_file.write(image_data)

在你可以将图像作为文件使用之后, 在Photo模型中使用paperclip保存图像:

Photo.new(image: image).save

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接