【问题标题】:RESTful file uploads with CarrierWave使用 CarrierWave 上传 RESTful 文件
【发布时间】:2011-10-06 19:48:17
【问题描述】:

我正在尝试为文件上传构建 API 后端。我希望能够使用具有 Base64 编码的文件字符串的 POST 请求上传文件。服务器应解码字符串,并使用 CarrierWave 保存文件。到目前为止,这是我所拥有的:

照片.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
 => #<Photo _id: 4e21b9a31d41c817b9000001, created_at: nil, updated_at: nil, _type: nil, user_id: nil, image_file_filename: nil> 
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 

full

问题似乎与将 Base64 解码字符串转换为文件的过程有关。 CarrierWave 似乎需要一个 File 对象,而我却给它一个字符串。那么如何将该 String 转换为 File 对象。我希望这种转换不会将任何内容保存到文件系统中,只需创建对象并让 CarrierWave 完成剩下的工作。

【问题讨论】:

  • 我知道这与您所要求的不同,但我放弃了 Paperclip 和 CarrierWave 以支持极其强大的 DragonFly。查看“使用访问器”下的markevans.github.com/dragonfly/file.Models.html
  • @kain 我现在正在使用carrierwave.. 想了解更多关于蜻蜓的体验
  • 出于某种原因,每次我使用 Paperclip 和 CarrierWave 时,我都会使用自定义补丁,尤其是 Paperclip。 DragonFly 允许在没有先例的情况下进行自定义,而无需修补任何东西,而且它的工作坚如磐石。非平凡的配置很难设置,但一旦你掌握了,你就可以做任何事情。例子?我的应用程序需要 robustreal mime 类型,因为它们也写在远程存储标头上。查看我的门票:bit.ly/pSv6EE
  • 谢谢,是的.. 我也不得不修补carrierwave来解决一些烦人的事情

标签: ruby-on-rails ruby rest file-upload carrierwave


【解决方案1】:

CarrierWave 也接受 StringIO,但它需要 original_filename 方法,因为它需要它来确定文件名和进行扩展检查。 Rails 2 和 3 之间的操作方式发生了变化,这两种方法都是:

导轨 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

【讨论】:

  • 我有点失望,我必须对 StringIO 进行猴子补丁,但它有效!
  • 如果只是单机使用,可以这样写:io = StringIO.new(Base64.decode64(encoded_img)); def io.original_filename; "foobar.png";结束
  • 从技术上讲,您不是在修补 StringIO,而是在创建一个继承自 StringIO 并添加了额外属性 original_filename 的新类。根本不是猴子补丁。
  • 哈哈,你知道回顾这条评论你是完全正确的。令人惊讶的是花了这么长时间才有人抓住它。好像已经修好了。
  • the documentation 中指定了另一种无需修补StringIO 的方法:def s.original_filename; "foobar.png"; end
【解决方案2】:

您不必对 StringIO 进行monkeypatch 或将其中的任何内容放入您的模型中。您可以在上传器定义中覆盖 cache!() 方法。或者你可以更进一步,为自己制作一个模块。我的文件是来自 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

【讨论】:

    【解决方案3】:
    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

    【讨论】:

      猜你喜欢
      • 2013-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多