Многокомпонентная загрузка файлов в Ruby - PullRequest
7 голосов
/ 06 июня 2009

Я просто хочу загрузить изображение на сервер с помощью POST. Как бы просто ни звучала эта задача, в Ruby, похоже, нет простого решения.

В моем приложении я использую WWW :: Mechanize для большинства вещей, поэтому я тоже хотел использовать его для этого, и у меня был такой источник:

f = File.new(filename, File::RDWR)
reply = agent.post(
    'http://rest-test.heroku.com',
    {
         :pict       =>  f,
         :function   =>  'picture2',
         :username   =>  @username,
         :password   =>  @password,
         :pict_to    =>  0,
         :pict_type  =>  0
    }
)
f.close

Это приводит к тому, что файл на сервере полностью готов к мусору и выглядит зашифрованным повсюду:

альтернативный текст http://imagehub.org/f/1tk8/garbage.png

Моим следующим шагом было понижение WWW :: Mechanize до версии 0.8.5. Это работало до тех пор, пока я не попытался его запустить, что привело к ошибке, например «Модуль не найден в hpricot_scan.so». Используя инструмент Dependency Walker, я смог выяснить, что hpricot_scan.so нужен msvcrt-ruby18.dll. Тем не менее, после того, как я поместил этот .dll в мою папку Ruby / bin, он дал мне пустое окно с ошибкой, откуда я не мог отлаживать дальше. Таким образом, проблема здесь в том, что Mechanize 0.8.5 зависит от Hpricot вместо Nokogiri (который работает безупречно).


Следующая идея заключалась в использовании другого гема, поэтому я попытался использовать Net :: HTTP. После короткого исследования я обнаружил, что в Net :: HTTP нет встроенной поддержки многокомпонентных форм, и вместо этого вам нужно создать класс, который кодирует и т.д. для вас. Самым полезным, что я мог найти, был Multipart-класс Станислава Витвицкого . Пока этот класс выглядел хорошо, но он не делает то, что мне нужно, потому что я не хочу публиковать только файлов, я также хочу публиковать нормальные данные, а это невозможно с его классом.


Моя последняя попытка была использовать RestClient . Это выглядело многообещающе, так как были примеры того, как загружать файлы. И все же я не могу заставить его опубликовать форму как составную часть.

f = File.new(filename, File::RDWR)
reply = RestClient.post(
    'http://rest-test.heroku.com',
    :pict       =>  f,
    :function   =>  'picture2',
    :username   =>  @username,
    :password   =>  @password,
    :pict_to    =>  0,
    :pict_type  =>  0
)
f.close

Я использую http://rest -test.heroku.com , который отправляет запрос на отладку, если он отправлен правильно, и я всегда получаю это обратно:

POST http://rest-test.heroku.com/ with a 101 byte payload,
content type application/x-www-form-urlencoded
{
    "pict" => "#<File:0x30d30c4>",
    "username" => "s1kx",
    "pict_to" => "0",
    "function" => "picture2",
    "pict_type" => "0",
    "password" => "password"
}

Это ясно показывает, что он не использует multipart/form-data в качестве типа контента, но стандарт application/x-www-form-urlencoded, хотя он определенно видит, что pict - это файл.


Как я могу загрузить файл в Ruby в многокомпонентную форму, не используя всю кодировку и выравнивание данных?

Ответы [ 2 ]

9 голосов
/ 06 июня 2009

Длинная проблема, короткий ответ: мне не хватало двоичного режима для чтения изображения под Windows.

f = File.new(filename, File::RDWR)

должно было быть

f = File.new(filename, "rb")

1 голос
/ 19 февраля 2011

Другой метод - использовать Bash и Curl. Я использовал этот метод, когда я хотел проверить несколько загрузок файлов.

bash_command = 'curl -v -F "file=@texas.png,texas_reversed.png"                         
http://localhost:9292/fog_upload/upload'
command_result = `#{bash_command}` # the backticks are important <br/>
puts command_result
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...