【问题标题】:Rails Carrierwave Base64 image uploadRails Carrierwave Base64 图片上传
【发布时间】:2013-01-31 17:50:02
【问题描述】:

使用 Carrierwave 将图像从客户端上传到 Rails 后端的最佳方式是什么。现在我们的 iOS 开发人员正在以 base64 格式发送文件,所以请求是这样的:

"image_data"=>"/9j/4AAQSkZJRgABAQAAAQABAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAHqADAAQAAAABAAAAHgAAAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAAeAB4DAREAAhEBAxEB/8QAHwAAAQUBAQE....

所以,我的问题实际上是两个问题。我应该告诉他以不同的文件格式发送吗?如果 base64 是发送这些文件的正确方式,那么我该如何在carrierwave中处理它们?

【问题讨论】:

  • iOS 应用无法发送标准的分段文件上传 POST 请求吗?
  • 我真的不确定。我不会在 iOS 中编码
  • 我也不会,但我会询问您的 iOS 开发人员这是否可能,因为从 Rails 的角度来看,这似乎是最明智的选择,而不是处理 base_64 编码数据。
  • 我认为你是对的,我应该问一下,谢谢你的建议

标签: ruby-on-rails ruby carrierwave


【解决方案1】:

我认为一种解决方案是将解码的数据保存到文件中,然后将此文件分配给已安装的上传器。然后删除那个文件。

另一个(内存中)解决方案可以是这个:

# define class that extends IO with methods that are required by carrierwave
class CarrierStringIO < StringIO
  def original_filename
    # the real name does not matter
    "photo.jpeg"
  end

  def content_type
    # this should reflect real content type, but for this example it's ok
    "image/jpeg"
  end
end

# some model with carrierwave uploader
class SomeModel
  # the uploader
  mount_uploader :photo, PhotoUploader

  # this method will be called during standard assignment in your controller
  # (like `update_attributes`)
  def image_data=(data)
    # decode data and create stream on them
    io = CarrierStringIO.new(Base64.decode64(data))

    # this will do the thing (photo is mounted carrierwave uploader)
    self.photo = io
  end

end

【讨论】:

  • 我很好奇非内存解决方案是什么?我应该担心这个解决方案的性能吗?
  • 如何调用 image_data=(data)?
  • 如何检测内容类型?
  • 为了不污染日志,我把 config.filter_parameters += [:password, :image_data] 放在了配置中
  • 我正在使用从画布生成的数据 URL。我的最终图像无效。您必须确保传入的数据只是数据,没有“data:image/png”部分。
【解决方案2】:

老问题,但我不得不做类似的事情,从通过 json 请求传递的 base64 字符串上传图像。这就是我最终要做的:

#some_controller.rb
def upload_image
  set_resource
  image = get_resource.decode_base64_image params[:image_string]
  begin
    if image && get_resource.update(avatar: image)
      render json: get_resource
    else
      render json: {success: false, message: "Failed to upload image. Please try after some time."}
    end
  ensure
    image.close
    image.unlink
  end
end

#some_model.rb
def decode_base64_image(encoded_file)
  decoded_file = Base64.decode64(encoded_file)
  file = Tempfile.new(['image','.jpg']) 
  file.binmode
  file.write decoded_file

  return file
end

【讨论】:

    【解决方案3】:

    您可以使用Carrierwave-base64 Gem 轻松实现这一点,您不必自己处理数据,您只需添加 gem 并从

    更改您的模型
    mount_uploader :file, FileUploader
    

    mount_base64_uploader :file, FileUploader
    

    就是这样,现在你可以轻松地说:

    Attachment.create(file: params[:file])
    

    【讨论】:

    • 这对我有用,但我花了一段时间才弄清楚如何将图像数据添加到控制器中的用户对象中。原始 base64 字符串通过“avatar”参数进入控制器,我的用户模型有一个载波 base64uploader,也称为“avatar”,所以它看起来像这样:user.update_attributes(avatar:“data:image/png;base64” + 参数[:avatar])
    • 我需要添加数据前缀。添加 gem "data:image/png;base64," + params[:image_file] 后,它对我有用。谢谢@gravy
    猜你喜欢
    • 2015-11-29
    • 1970-01-01
    • 2015-03-15
    • 2017-03-02
    • 2014-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多