6

ファイルアップロード用の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
 => #<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 

満杯

この問題は、Base64でデコードされた文字列をファイルに変換するプロセスに関連しているようです。CarrierWaveはFileオブジェクトを期待しているようですが、代わりに文字列を指定しています。では、その文字列をFileオブジェクトに変換するにはどうすればよいですか。この変換では、ファイルシステムに何も保存せず、オブジェクトを作成して、CarrierWaveに残りを任せたいと思います。

4

3 に答える 3

24

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
于 2011-07-16T19:09:07.487 に答える
1

StringIOにモンキーパッチを適用したり、モデルにこれを追加したりする必要はありません。アップローダー定義のcache!()メソッドをオーバーライドできます。または、さらに一歩進んで、自分で含めるモジュールを作成することもできます。私のファイルは、jsonドキュメントからのシリアル化された文字列です。渡されるオブジェクトは次のようになります{:filename =>'something.jpg'、:filedata=>base64文字列}。

これが私のモジュールです:

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

そして、それをアップローダーに含めることができます。uploaders / some_uploader.rb:

class SomeUploader < CarrierWave::Uploader::Base

  include CarrierWave::Uploader::BackboneLink
于 2013-09-13T16:27:33.653 に答える
0
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

また、carrierwavewikihttps://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Upload-from-a-string-in-Rails-3も参照してください。

于 2013-07-03T15:01:18.220 に答える