RubyでHTTPのPostを使用してファイルをアップロードするスクリプトを作りたいです。試しにコメント欄のような物を作ってみましたが、500でエラーが発生してしまいます。


request["content-type"] = "multipart/form-data, boundary=#{boundary}"
の末尾に改行(\r\n)を入れるとエラーは発生しませんが、データとして認識してくれません。つまり、CGIのデータとして入ってきません。

有力な回答をして頂いた方に優先的にポイントをプレゼント致します。

回答の条件
  • 1人5回まで
  • 登録:2008/06/30 15:34:50
  • 終了:2008/06/30 22:48:51

ベストアンサー

id:rubikitch No.1

るびきち回答回数120ベストアンサー獲得回数222008/06/30 22:34:24

ポイント100pt

httpclient(gem install httpclient)を使うと楽です。

require 'rubygems'
require 'httpclient'

boundary = "123456"
c = HTTPClient.new
open("/r/hoge.txt") do |file|
  postdata = { "first_name" => "michael", "last_name" => "jackson",
    "file" => file }
  puts c.post_content("http://localhost:9998/hoge.cgi", postdata,
    "content-type" => "multipart/form-data, boundary=#{boundary}")
end

動作確認のCGIスクリプトはこんなの。

#!/usr/local/bin/ruby
require 'cgi'
cgi = CGI.new
cgi.out("type"=>"text/plain") {
  cgi["file"].read
}

http://d.hatena.ne.jp/rubikitch/20080627/1214504190

id:ichiroc

ありがとうございます!!

動作確認できました!!

2008/06/30 22:48:16

その他の回答(1件)

id:rubikitch No.1

るびきち回答回数120ベストアンサー獲得回数222008/06/30 22:34:24ここでベストアンサー

ポイント100pt

httpclient(gem install httpclient)を使うと楽です。

require 'rubygems'
require 'httpclient'

boundary = "123456"
c = HTTPClient.new
open("/r/hoge.txt") do |file|
  postdata = { "first_name" => "michael", "last_name" => "jackson",
    "file" => file }
  puts c.post_content("http://localhost:9998/hoge.cgi", postdata,
    "content-type" => "multipart/form-data, boundary=#{boundary}")
end

動作確認のCGIスクリプトはこんなの。

#!/usr/local/bin/ruby
require 'cgi'
cgi = CGI.new
cgi.out("type"=>"text/plain") {
  cgi["file"].read
}

http://d.hatena.ne.jp/rubikitch/20080627/1214504190

id:ichiroc

ありがとうございます!!

動作確認できました!!

2008/06/30 22:48:16
id:poch-7003 No.2

poch-7003回答回数43ベストアンサー獲得回数82008/06/30 22:45:42

ポイント10pt

こんな感じでしょうか。

contents.txt

1.hoge
2.hogehoge
3.hogehogehoge
4.hogehogehogehoge

upload.cgi

#!/usr/bin/ruby
# vim:set ts=2 sw=2 sts=2 si ai nu et ft=ruby:
#
# [upload.cgi]
#

require "cgi"

cgi = CGI::new
files = cgi["file1"]

print "Content-type: text/html\r\n\r\n"
puts "filename: " + files.original_filename
puts "----------------"
puts files.read
puts "----------------"

exit(0)

post.cgi

#!/usr/bin/ruby
# vim:set ts=2 sw=2 sts=2 si ai nu et ft=ruby:
#
# [post.cgi]
#

require 'net/http'

boundary='-----------------------3948A8'
contents = File::open("./contents.txt").read

data =  %[--#{boundary}] + "\r\n"
data << %[Content-Disposition: form-data; name="file1"; filename="contents.txt"] + "\r\n"
data << %[Content-Type: text/plain] + "\r\n\r\n"

data << contents
data << %[\r\n--#{boundary}--\r\n]

header ={
  'Content-Length' => data.length.to_s,
  'Content-Type' => "multipart/form-data; boundary=#{boundary}"
}

Net::HTTP.start('localhost', 80) do |http|
  r= http.post('/~hoge/cgi-bin/upload.cgi', data, header)
  print r.body
end

exit(0)
  • id:ichiroc

    require'net/http'
    require "pp"
    require'uri'
    def make_post_data(url , boundary , file ={ }, post_data={ })
    type = {
    ".txt" => "text/plain",
    ".gif" => "image/gif",
    ".jpg" => "image/jpeg",
    ".jpeg" => "image/jpeg",
    ".png"=> "image/png",
    ".flv" => "video/x-flv",
    ".wmv" => "video/x-ms-wmv"
    }
    data = ""
    post_data.each do |key , value|
    data << "----#{boundary}\r\n"
    data << "content-disposition: form-data; name=\"#{key}\"\r\n"
    data << "\r\n"
    data << "#{value}\r\n"
    end

    file.each do |name , path|
    data << "----#{boundary}\r\n"
    data << "content-disposition: form-data; name=\"#{name}\"; filename=\"#{File.basename(path)}\"\r\n"
    data << "Content-Type: #{type.fetch(File.extname(path))}\r\n"
    # data << "Content-Transfer-Encoding: binary\r\n"
    data << "\r\n"
    data << File.read(path)
    end
    data << "\r\n"
    data << "----#{boundary}\r\n"
    data
    end
    boundary = "123456"

    data = make_post_data("http://localhost:3000/movie/new",
    boundary,
    { "file" => "c:\\text.txt"},
    {"first_name"=>"michael","last_name"=>'jackson'})
    uri = URI.parse('http://localhost:3000/test/new')
    request = Net::HTTP::Post.new(uri.path)
    request["content-type"] = "multipart/form-data, boundary=#{boundary}"
    request.body = data

    http = Net::HTTP.start(uri.host,uri.port)
    res = http.request(request)
    puts res.body
  • id:ichiroc
    id:poch-7003 様

    ちょうどすれ違いで質問を閉めてしまいましたが、ありがとうございました。
    実装の仕方でとても勉強になりました。

この質問への反応(ブックマークコメント)

トラックバック

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません