UpImage.cgi
出典: YKAwiki
概要
Flash から画像ファイルと保存先ファイル名を受け取り、ファイルを作成して書き込む CGI 。Ruby を使用する。
Flash 側で既にファイルサイズ、参照するファイル名などについて適切かどうかはチェックしているが、直接 CGI を触られた場合に備えファイルサイズとファイル名の先頭文字だけは再検査する。
(stub) http://ja2yka.homeip.net/~taka/cgi-bin/ruby/upImage.html で画像のアップロードができます。
また、アップロードした画像は http://ja2yka.homeip.net/~taka/cgi-bin/ruby/loaderTest.swf で確認できます。(この画像をロードする swf をタイピングゲーム本体に組み込む予定)
ただし *.png 以外は表示されない場合があるでしょう。また、画像を消したい場合は上書きするしかないので注意。
open() について。Ruby では特に `|' がヤバイ(と思う)。
(Rubyリファレンスマニュアル-組み込み関数 の、文中「ファイル名が `|' で始まる時には...」を参照)
ソース
解説はちょっと待ってね
#!/usr/local/bin/ruby # アルファベット大文字 ([A-Z]) で始まる識別子は定数。 # 大盤振る舞いの 300kB FILE_MAX_SIZE = 300*1024 # cgi ライブラリの使用 require "cgi" # .html のほうで # <form method="post" action="./upImage.cgi" enctype="multipart/form-data"> # で渡しているので注意(画像ファイルのバイト列、画像の名前は添付ファイルとして渡されている。) formData = CGI.new print "Content-type: text/html\n\n" puts "image uploader" puts "uploading..." puts "</br>" # Flash から渡された'imageData' から、ハッシュ(連想配列)操作的に # 画像データを StringIOオブジェクトとして取得 imageData = formData['imageData'] if imageData.size > FILE_MAX_SIZE then puts "too large file" exit end puts "imageData size ok. size: " puts imageData.size puts "</br>" # 同様に Flash から渡された'imageName' から、 # 画像の名前のための文字列を取得。 # この名前のファイルを作成し、書き込む。 fileName = formData['imageName'] if fileName.size < 6 then puts "too short fileName" exit end # ファイル名が `|' で始まる時には続く文字列をコマンドとして起動し、 # コマンドの標準入出力に対してパイプラインを生成する。 # Flash 側で `|' で始まるファイル名は作成されないようになっているが、 # Flash 以外からアクセスされた時に怖いのでちょっとした処理を。 # StringIO を文字列に直す。 fileName2 = fileName.read if fileName2[0, 1] == "|" then fileName2 = "illegal_fileName_" + fileName2 puts fileName2 end fileName2 = "./" + fileName2 puts "fileName length ok. fileName : " puts fileName2 puts "</br>" # 書き込み先ファイル fileName2 をオープン。File オブジェクトを返す。 # "wb": ファイルをバイナリ書き込みモードでオープン。 # ファイルがすでに存在していればその内容を空にして書き込む。 # ファイルのアクセス権はデフォルト 0666 。 # open をブロックとともに呼び出すことで、 # ファイルをオープンしてブロックを実行し、 # ブロックの実行が終了するとファイルをクローズする。 # f はイテレータ # puts は File のメソッドでなく組み込み関数。 open(fileName2, "wb") do |f| f.puts imageData.read end puts "uploaded." puts "</br>" puts "http://ja2yka.homeip.net/~taka/cgi-bin/ruby/loaderTest.swf でチェックしてみて"
Flash から呼ぶとなんかおかしい
Flash からファイルをアップロードしようとしたところ、冒頭の
formData = CGI.new
でエラーが出てなんともかんとも。サーバーのエラーログは以下の通り
/usr/local/lib/ruby/1.8/cgi.rb:979:in `read_multipart' no content body ( EOFError ) from /usr/local/lib/ruby/1.8/cgi.rb:1104:in `initialize_query' from /usr/local/lib/ruby/1.8/cgi.rb:2270:in `initialize' from /home/taka/public_html/cgi-bin/ruby/upImage.cgi:23
最後の upImage.cgi:23 が formData = CGI.new のところ。
で、問題の /usr/local/lib/ruby/1.8/cgi.rb:979近辺は以下の通り
# start multipart/form-data
stdinput.binmode if defined? stdinput.binmode
boundary_size = boundary.size + EOL.size
content_length -= boundary_size
status = stdinput.read(boundary_size)
if nil == status
raise EOFError, "no content body"
elsif boundary + EOL != status
raise EOFError, "bad content body"
end
stdinput は stdin のエイリアス。HTML ならエラーでないのに、Flashではなぜか文字列が読めてない感じ?Flash がどうやって渡してるのかわからん。POST リクエストに関しては
multipart/form-data の Content-Type エレメント name 属性が "Filedata"、filename 属性が元のファイル名に設定された Content-Disposition エレメント ファイルのバイナリコンテンツ
としかヘルプに書いてない。 わからん・・ということで php に逃げます。
