使用CarrierWave上传RESTful文件
我正在尝试为文件上传构建API后端。 我希望能够使用具有Base64编码的文件字符串的POST请求上传文件。 服务器应解码字符串,并使用CarrierWave保存文件。 这是我到目前为止所拥有的:
photo.rb:
class Photo include Mongoid::Document include Mongoid::Timestamps mount_uploader :image_file, ImageUploader end
image_uploader.rb:
class ImageUploader < CarrierWave::Uploader::Base storage :file def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end end
Rails控制台:(摘要)
ruby-1.8.7-p334 :001 > img = File.open("../image.png") {|i| i.read} => "\377 JFIF\000\001\002\001\000H\000H\000\000\377 Photoshop 3.0\0008BIM\003... ruby-1.8.7-p334 :003 > encoded_img = Base64.encode64 img => 3af8A\nmLpplt5U8q+a7G2... ruby-1.8.7-p334 :005 > p = Photo.new => # ruby-1.8.7-p334 :006 > p.user_id = 1 => 1 ruby-1.8.7-p334 :007 > p.image_file = Base64.decode64 encoded_img \255 =\254\200 7u\226 \230 -zh wT\253% \036ʉs\232Is M\215 ˿6\247\256\177... ruby-1.8.7-p334 :008 > p.save => true ruby-1.8.7-p334 :009 > p.image_file.url => nil
充分
该问题似乎与将Base64解码的字符串转换为文件的过程有关。 CarrierWave似乎期待一个File对象,而我给它一个String。 那么如何将该String转换为File对象。 我希望这种转换不是为文件系统保存任何东西,只需创建对象并让CarrierWave完成剩下的工作。
CarrierWave也接受一个StringIO,但是它需要一个original_filename
方法,因为它需要它来确定文件名并进行扩展检查。 如何在Rails 2和3之间进行更改,以下是两种方法:
Rails 2
io = StringIO.new(Base64.decode64(encoded_img)) io.original_filename = "foobar.png" p.image_file = io p.save
在Rails 3中,您需要创建一个新类,然后手动添加original_filename
class FilelessIO < StringIO attr_accessor :original_filename end io = FilelessIO.new(Base64.decode64(encoded_img)) io.original_filename = "foobar.png" p.image_file = io p.save
您不必使用monkeypatch StringIO或将任何内容放入模型中。 您可以覆盖上传器定义中的缓存!()方法。 或者你可以更进一步,为自己制作一个模块。 我的文件是来自json文档的序列化字符串。 传入的对象看起来像{:filename =>’something.jpg’,:filedata => base64 string}。
这是我的模块:
module CarrierWave module Uploader module BackboneLink def cache!(new_file=sanitized_file) #if new_file isn't what we expect just jump to super if new_file.kind_of? Hash and new_file.has_key? :filedata #this is from a browser, so it has all that 'data:..' junk to cut off. content_type, encoding, string = new_file[:filedata].split(/[:;,]/)[1..3] sanitized = CarrierWave::SanitizedFile.new( :tempfile => StringIO.new(Base64.decode64(string)), :filename => new_file[:filename], :content_type => content_type ) super sanitized else super end end end end end
然后我可以将它包含在上传器中。 上传/ some_uploader.rb:
class SomeUploader < CarrierWave::Uploader::Base include CarrierWave::Uploader::BackboneLink
class AppSpecificStringIO < StringIO attr_accessor :filepath def initialize(*args) super(*args[1..-1]) @filepath = args[0] end def original_filename File.basename(filepath) end end
另请参阅carrierwave wiki https://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Upload-from-a-string-in-Rails-3
- Rails背景图片上传
- Rails 4,Carrierwave-aws,图像在本地上传到amazon s3但未投放到生产中(Openshift)
- Rails – Errno :: EACCES(权限被拒绝)上传用户的头像时
- 使用Carrierwave(HTML5)一次上传多个文件到Rails应用程序
- 如何使用carrierwave将文件发送给用户?
- Ruby on Rails – Carrierwave获取图像尺寸宽度和高度
- 加载到Heroku时Carrierwave / fog / AWS问题“无法加载此类文件 – 雾”
- 使用carrierwave在gif中获取第一张图像
- 为什么carrierwave导致NameError:未初始化的常量Micropost :: PictureUploader错误?