• ベストアンサー

Rubyでファイル転送

Rubyでファイル転送のcgiを作成してみましたが動作しません。 実行後は選択したファイル(aa.jpg等)が作成されますが、 容量がゼロです。(FTPで確認) Apacheエラー------ undefined local variable or method `input'for main:Object(NameError) 変数nameはファイル名であり、c:\等は含まれていません。 ruby1.8.2------ #!/usr/bin/ruby -Ku print "Content-type: text/html\n\n" require "cgi" require 'net/ftp' input = CGI.new.params; cgi = CGI.new $name = input["name"][0] if input["name"][0] open("/home/movies/#{$name}","w") do |fh| fh.binmode fh.write imput['name'][0].read end end html------ <form action="***" method="get" enctype="multipart/form-data"> <input type="file" name="name" size="30"> <input type="submit" name="regist" value="選択"></form>

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

open のブロックの中で fh.write の引数に使われてるのが 'input' じゃなくて 'imput' になってるのは 単にここに書いたときの間違いですか? Apacheのログに undefined local ... ってあるんだから これでなくても同様のtypoだったりしませんか?

dosparas
質問者

補足

ご回答ありがとうございます。 fh.write imput['name'][0].readを fh.write input['name'][0].readへ訂正したところ、 undefined method `read' for "aa.jpg":String (NoMethodError) となりました。 readメソッドが定義されていないエラーだと思われますが、 require "cgi"では不十分なのでしょうか?

その他の回答 (5)

  • notnot
  • ベストアンサー率47% (4900/10358)
回答No.6

#3です。 HTMLをちゃんと見てなかった。form を method="POST" にしてください。

dosparas
質問者

補足

ご回答ありがとうございます。 下記のようなエラーが出ました。調査してみます。 /usr/lib/ruby/1.8/cgi.rb:981:in `read_multipart': no content body (EOFError) from /usr/lib/ruby/1.8/cgi.rb:1108:in `initialize_query' from /usr/lib/ruby/1.8/cgi.rb:2274:in `initialize' from /home/www/prog/test.cgi:5:in `new' from /home/www/prog/test.cgi:5 ---test.cgi #!/usr/bin/ruby -Ku print "Content-type: text/html\n\n" # require "cgi" input = CGI.new.params; cgi = CGI.new if input["regist"][0] open("/home/movies/outfile","wb") do |fh| fh.write CGI.new.params["name"].read end end puts <<-"EOB" <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title></title> </head> <body> <form action="test.cgi" method="POST" enctype="multipart/form-data"> <input type="file" name="name" size="30"> <input type="submit" name="regist" value="選択"></form> </body></html> EOB

回答No.5

あれ? ruby のバージョンは1.8.2なんですよね(これもちょっと古いですけど)。 cgi - Rubyリファレンスマニュアル http://www.ruby-lang.org/ja/man/html/cgi.html#footmark-2 にある 1.8以降の cgi.rbの動作じゃないような気がするんですが。

dosparas
質問者

補足

ご回答ありがとうございます。 #ruby -v ruby 1.8.5 (2006-08-25) [i486-linux] 新規で1.8をインストールしたもので、 1.6からのアップデートはしておりません。

回答No.4

>readメソッドが定義されていませんと表示されました。 #3の回答にあるスクリプトの input = CGI.new.params["name"][0] を input = CGI.new.params["name"] と変えるとどうなりますか? if の判定も変更しないといけないような気がするけどとりあえず。

dosparas
質問者

補足

undefined method `read' for ["aa.jpg"]:Array (NoMethodError) となりました。 質問文のhtmlはcgiで生成しているもので、同一ファイルでしたが、 これをcgi部とhtml部の2つのファイルに分けて試したところ、 cgiファイルが開きませんでした。 (104)Connection reset by peer: ap_content_length_filter: apr_bucket_read() failed こちらが原因かも分かりませんので、調べています。

  • notnot
  • ベストアンサー率47% (4900/10358)
回答No.3

htmlを見る限り、ファイル転送じゃなくファイルタイプのinputタグを使ったファイルのアップロードをしたいと思われます。 従って、'net/ftp' は関係ありません。 参考にしたスクリプトが悪いのかな? #!/usr/bin/ruby -Ku print "Content-type: text/html\n\n" require "cgi" input = CGI.new.params["name"][0] if input open("/home/movies/outfile","wb") do |fh| fh.write input.read end end アップロードしたクライアント側のファイル名は、 value.original_filename ですが、これをそのままサーバー側のファイル名に使ったりすると脆弱性(セキュリティーホール)になって、システムを壊される危険があります。表示する程度なら良いですが、ファイル名としては使えません。

dosparas
質問者

補足

ご回答ありがとうございます。 readメソッドが定義されていませんと表示されました。 undefined method `read' for "aa.jpg":String (NoMethodError)

回答No.2

>undefined method `read' for "aa.jpg":String (NoMethodError) input['name'][0] は文字列(で、内容が'aa.jpg')なのでそれに readメソッドはありません。 ここでaa.jpg というファイルの内容を持って来たいのなら 読み込んでこないと。 Windows でなければ IO.read(input['name'][0]) でいいと思いますがこれだとバイナリモードとかの指定ができないので、 File.open(input['name'][0], 'rb'){|rh| rh.read} とかでしょうか。

dosparas
質問者

補足

File.open(input['name'][0], 'rb'){|rh| rh.read } により、取得を行いましたが、 No such file or directory - aa.htmlとなります。 input['name'][0]を"D:\aa.html"へ変更しても No such file or directory - D:\aa.htmlとなります。 おそらくサーバ上(linux)のD:\aa.htmlを参照していると思いますが、 これをクライアントの参照にするにはどのようにすればよろしいでしょうか?