Rails 3 получает исходные данные и записывает их в файл tmp - PullRequest
13 голосов
/ 16 января 2011

Я работаю над реализацией Ajax-Upload для загрузки фотографий в мое приложение Rails 3.Документация гласит:

  1. Для IE6-8, Opera, более старых версий других браузеров вы получаете файл, как обычно при обычной загрузке на основе формы.

  2. Для браузеров, которые загружают файл с индикатором выполнения, вам необходимо получить необработанные данные поста и записать их в файл.

ИтакКак я могу получить необработанные данные в моем контроллере и записать их в файл tmp, чтобы мой контроллер мог затем обработать их?(В моем случае контроллер выполняет некоторые манипуляции с изображениями и сохраняет их в S3.)

Некоторая дополнительная информация:

Поскольку я настроен прямо сейчас, пост передает следующие параметры:

Parameters:
{"authenticity_token"=>"...", "qqfile"=>"IMG_0064.jpg"}

... и действие CREATE выглядит следующим образом:

def create
    @attachment = Attachment.new
    @attachment.user = current_user
    @attachment.file = params[:qqfile]
    if @attachment.save!
        respond_to do |format|
            format.js { render :text => '{"success":true}' }
        end
    end
end

... но я получаю эту ошибку:

ActiveRecord::RecordInvalid (Validation failed: File file name must be set.):
  app/controllers/attachments_controller.rb:7:in `create'

Ответы [ 4 ]

27 голосов
/ 16 января 2011

Это потому, что params [: qqfile] - это не объект UploadedFile, а строка, содержащая имя файла.Содержимое файла хранится в теле запроса (доступно с помощью request.body.read ).Конечно, вы не можете забыть обратную совместимость, поэтому вам все равно нужно поддерживать UploadedFile.

Поэтому, прежде чем вы сможете обработать файл единообразным способом, вы должны поймать оба случая:

5 голосов
/ 14 апреля 2011

попробуйте, добавьте lib / qq_file.rb:

# encoding: utf-8
require 'digest/sha1'
require 'mime/types'

# Usage (paperclip example)
# @asset.data = QqFile.new(params[:qqfile], request)
class QqFile < ::Tempfile

  def initialize(filename, request, tmpdir = Dir::tmpdir)
    @original_filename  = filename
    @request = request

    super Digest::SHA1.hexdigest(filename), tmpdir
    fetch
  end

  def self.parse(*args)
    return args.first unless args.first.is_a?(String)
    new(*args)
  end

  def fetch
    self.write @request.raw_post
    self.rewind
    self
  end

  def original_filename
    @original_filename
  end

  def content_type
    types = MIME::Types.type_for(@request.content_type)
      types.empty? ? @request.content_type : types.first.to_s
  end
end

в assets_controller, введите это:

def create
  @asset ||= Asset.new(params[:asset])

  @asset.assetable_type = params[:assetable_type]
  @asset.assetable_id = params[:assetable_id] || 0
  @asset.guid = params[:guid]
  @asset.data = QqFile.parse(params[:qqfile], request)
  @asset.user_id = 0
  @success = @asset.save

  respond_with(@asset) do |format|
    format.html { render :text => "{'success':#{@success}}" }
    format.xml { render :xml => @asset.to_xml }
    format.js { render :text => "{'success':#{@success}}"}
    format.json { render :json => {:success => @success} }
  end
end

javascript:

var photo_uploader = new qq.FileUploader({
  element: document.getElementById('photo-button'),
  multiple: true,
  action: '/assets',
  allowedExtensions: ['png', 'gif', 'jpg', 'jpeg'],
  sizeLimit: 2097152,
  params: {guid: $('#idea_guid').val(), assetable_type: 'Idea', klass: 'Picture', collection: true}
});
1 голос
/ 28 ноября 2012

Другое решение:

gem 'rack-raw-upload', :git => 'git://github.com/tb/rack-raw-upload.git'

и в config.ru:

 require 'rack/raw_upload'
 use Rack::RawUpload

и используйте params [: file] в контроллере.

0 голосов
/ 11 января 2012

Вместо создания временного файла с беспорядком, вы можете использовать StringIO.Смотрите мой ответ о CarrierWave, здесь: https://stackoverflow.com/a/8812976/478354

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...