2009-06-06 24 views
7

Tôi chỉ muốn tải hình ảnh lên máy chủ có POST. Đơn giản như nhiệm vụ này nghe có vẻ không có giải pháp đơn giản nào trong Ruby.Tải lên tệp Multipart trong Ruby

Trong ứng dụng của tôi, tôi đang sử dụng WWW::Mechanize cho hầu hết mọi thứ vì vậy tôi muốn sử dụng nó cho việc này quá, và đã có một nguồn như thế này:

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

Điều này dẫn đến một tập tin hoàn toàn rác sẵn sàng trên máy chủ mà trông scrambled trên tất cả:

alt text http://imagehub.org/f/1tk8/garbage.png

bước tiếp theo của tôi là để hạ cấp WWW :: cơ giới hóa để phiên bản 0.8.5. Điều này làm việc cho đến khi tôi cố gắng chạy nó, mà không thành công với một lỗi như "Module không tìm thấy trong hpricot_scan.so". Sử dụng công cụ Dependency Walker tôi có thể tìm ra rằng hpricot_scan.so cần msvcrt-ruby18.dll. Tuy nhiên, sau khi tôi đặt rằng .dll vào thư mục Ruby/bin của tôi nó đã cho tôi một hộp lỗi rỗng từ nơi tôi không thể gỡ lỗi nhiều hơn nữa. Vì vậy, vấn đề ở đây là Mechanize 0.8.5 có sự phụ thuộc vào Hpricot thay vì Nokogiri (hoạt động hoàn hảo).


Ý tưởng tiếp theo là sử dụng một loại đá quý khác, vì vậy tôi đã thử sử dụng Net :: HTTP. Sau khi nghiên cứu ngắn tôi có thể tìm ra rằng không có hỗ trợ bản địa cho các hình thức multipart trong Net :: HTTP và thay vào đó bạn phải xây dựng một lớp học mã hóa vv cho bạn. Điều hữu ích nhất tôi có thể tìm thấy là Multipart-class by Stanislav Vitvitskiy. Lớp này có vẻ tốt cho đến nay, nhưng nó không làm những gì tôi cần, bởi vì tôi không muốn đăng chỉ tệp, tôi cũng muốn đăng dữ liệu bình thường và điều đó là không thể với lớp của anh ấy.


Nỗ lực cuối cùng của tôi là sử dụng RestClient. Điều này có vẻ đầy hứa hẹn, vì đã có ví dụ về cách tải tệp lên. Tuy nhiên, tôi không thể làm cho nó để gửi các hình thức như multipart.

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

Tôi đang sử dụng http://rest-test.heroku.com mà gửi lại yêu cầu để gỡ lỗi nếu nó được gửi một cách chính xác, và tôi luôn luôn có được trở lại này:

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" 
}

Điều này cho thấy rõ ràng rằng nó không sử dụng multipart/form-data như trang nội dung loại nhưng tiêu chuẩn application/x-www-form-urlencoded, mặc dù nó chắc chắn thấy rằng pict là một tập tin.


Làm thế nào tôi có thể tải lên một tập tin trong Ruby mẫu nhiều phần dữ liệu mà không cần thực hiện toàn bộ mã hóa và dữ liệu sắp xếp bản thân mình?

Trả lời

9

Vấn đề dài, câu trả lời ngắn: Tôi bị thiếu chế độ nhị phân để đọc hình ảnh trong Windows.

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

phải được

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

1

phương pháp khác là sử dụng Bash và Curl. Tôi đã sử dụng phương pháp này khi tôi muốn thử nghiệm nhiều tệp tải lên.

bash_command = 'curl -v -F "[email protected],texas_reversed.png"       
http://localhost:9292/fog_upload/upload' 
command_result = `#{bash_command}` # the backticks are important <br/> 
puts command_result 
Các vấn đề liên quan