ruby on rails: request.body.read показывает ошибку

#ruby #ajax #ruby-on-rails-3 #file-upload

#ruby #ajax #ruby-on-rails-3 #загрузка файла

Вопрос:

Я реализовал загрузку на основе AJAX в своем проекте rails.

Это мой пример кода. (Я следовал руководству отсюда.. https://github.com/valums/file-uploader )

 ********** Javascript Code **********

function createUploader(){
    var uploader = new qq.FileUploader({
        element: document.getElementById('file-uploader'),
        action: '/product/upload',        
    });
}

window.onload = createUploader;

********** Server side **********
def upload
  @filename = params['qqfile']

  f = File.open('home/files/'   @filename, "wb")
  str =  request.body.read
  f.write(str)
  f.close

  render :text => '{success:true}'
end
 

Когда я запускаю свой код, я получаю следующее сообщение об ошибке в строке «str = request.body.read»

 NoMethodError (undefined method `body' for #<ActionController::CgiRequest:0xb6cd71a0>): 
 

подробнее об ошибке: http://www.heypasteit.com/clip/01NE

Моя конфигурация:

 [mrblack@ home]# ruby -v  
ruby 1.8.7 (2008-08-11 patchlevel 72) [i686-linux]  
[mrblack@ home]# rails -v  
Rails 1.2.1  
[mrblack@ home]# gem -v  
1.8.6
 

Можете ли вы, пожалуйста, прояснить меня, что я сделал не так?

Комментарии:

1. похоже str = request.body.read , что строка здесь является ошибочной строкой, и у request объекта нет метода ‘body’.

2. Кроме того, почему в мире вы используете rails 1.2.1? Эта версия действительно старая.

3. О !!!.. Я рассмотрю это, спасибо. Bcz, моему проекту 7 лет. Вот почему я не могу обновить. 🙂

4. А, понятно… код rails семилетней давности… Ууух, страшно 😉

Ответ №1:

Потому что в Rails 1.2.1 ни ActionController ::CgiRequest, ни его родительский ActionController ::AbstractRequest не содержат метода ‘body’. Вы можете увидеть это, если посмотрите на эти страницы: cgi_process.rb и request.rb. Почему вы используете такую старую версию rails??

ОБНОВЛЕНИЕ @Mr. Black. Вы написали: «Не могли бы вы, пожалуйста, подсказать мне какой-либо альтернативный способ чтения входящего запроса, аналогичного этому объекту запроса». Вы используете библиотеку ‘file-uploader’ из github. Как я вижу, эта библиотека может загружать файлы на сервер двумя способами. Если у пользователя старые браузеры FF, Chrome или любая версия IE, эта библиотека отправляет запрос post в iframe. Если у пользователя современная библиотека версий FF или Chrome, подготавливается асинхронный post XMLHttpRequest. Поэтому в нашем контроллере rails мы должны обрабатывать обе ситуации. Например, для простоты мы хотим записать отправленные данные файла в какое-либо жестко запрограммированное место на диске.

 ******** app/controllers/greetings_controller.rb ********
class GreetingsController < ApplicationController
  def upload
    begin
      is_xhr = params[:qqfile].is_a? String
      data = is_xhr ? request.body : params[:qqfile]
      File.open("/some_place_on_disk/bar.txt", "w") { |f| f.write(data.read) }
      @result = {success: true}
      if is_xhr
        render :json => @result
      end
      # else render view
    rescue Exception => e
      logger.info e
      @result = {error: "Error has been encountered during the processing"}
    end
  end
end

******** app/views/upload.html.erb ********
<%= @result.to_json %>


******** config/routes.rb ********
.....
match '/upload' => 'greetings#upload', :via => :post
.....
 

Вы можете использовать demo.htm из проекта github, но вы должны поместить его в общую папку. Не забывайте о fileuploader.css и fileuploader.js ! 🙂 Вы должны изменить ‘action’ в функции createUploader на путь действия, в моем случае это будет ‘/ upload’

Комментарии:

1. Ах!! Да .. Спасибо @WarHog. Не могли бы вы подсказать мне какой-нибудь альтернативный способ чтения входящего запроса, аналогичного этому объекту запроса ?.

2. Я обновил предыдущий пост и написал несколько примеров. Удачи!