- 締切済み
Ruby1.8.7 ファイルアップロードCGI
CGI を使ったファイルのアップローダを作りたくて、今日初めて Ruby を触っていますが、質問があります。 アップロードするファイル本体以外の情報を name="version" で受け取って、保存するディレクトリを分けるようにしています。書きかけのコードは以下の通りです。(タブによるインデントが入らなかったので、アンダースコアで表現しています) ----------ここからソースコード---------- #!/usr/local/bin/ruby require "cgi" begin __print "Content-Type: text/plain\n\n" __cgi = CGI.new __print "Ruby version is " __print RUBY_VERSION,"\n" __print "filename = " __print cgi['upload_file'].original_filename, "\n" __file = cgi.params['version'][0] __if file.class == StringIO then ____print "File is StringIO Class.\n" ____print "version = " ____print cgi["version"].string, "\n" ____if File.exist? cgi["version"].string then ______print "このバージョンのディレクトリは既に存在しているため、ディレクトリは作成されませんでした。" ____else ______print "ディレクトリが存在しないので作成します。" ______Dir::mkdir(cgi["version"].string, 0755) ____end ____OUTPUT_DIR = (cgi["version"].string + "/") ____open(OUTPUT_DIR + cgi['upload_file'].original_filename, "w") {|fh| ____fh.binmode ____fh.write cgi['upload_file'].read ____} __else ____print "File is TempFile Class.\n" ____#ここから先が書きかけで分からない部分です。 __end rescue => e __print "Error!" + e end ----------ここまでソースコード---------- Ruby の CGI モジュールを使っていますが、受け取ったファイルが 10240 バイト未満だと StringIOオブジェクト、10240 バイト以上だと TempFile オブジェクトになるという規則があるそうで、オブジェクトの種類によって分岐させています。 StringIO オブジェクト(10240バイト未満の送信)の場合はこれで想定通りに動いたのですが、TempFile オブジェクトと判別された場合に、 version のテキストフィールドの文字列を print により表示(出力)したりディレクトリ名にしたりする方法が分かりません。また、ファイル本体 upload_file は TempFile オブジェクトの場合でも同じ記述でファイルに保存できますでしょうか? サーバにインストールされている Ruby のバージョンは 1.8.7 です。
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- notnot
- ベストアンサー率47% (4900/10358)
>StringIO と TempFile が区別無しに同じ記述で同じ動作になるのならそうしたいのですが、 ちゃんとしたプログラムを書けば同じです。 HTMLのinputタグで name="upload_file" と name="version" とあるようなのですが、どちらがファイルでどちらがテキストなのか、プログラム上で混乱しているように見えますよ。 >print cgi['upload_file'].original_filename, "\n" upload_fileがファイルのようである。 >file = cgi.params['version'][0] versionがファイルのようである。 >print cgi["version"].string, "\n" このstringと言うメソッドは何のつもりですか?cgi["version"]は何だと思っていますか?
- notnot
- ベストアンサー率47% (4900/10358)
なんか色々おかしい気がします。 そもそも、StringIOとTempFileを区別して処理したい理由は何でしょうか?普通は区別不要です。 >file = cgi.params['version'][0] これで、file には何が入るつもりですか? >if file.class == StringIO then その class って?意図通りですか? あと、このままだと脆弱性があります。送信されてきた文字列をそのまま使ってディレクトリやファイルの名前にしちゃだめです。文字列の正当性をチェックするか、適切にエスケープするかしないと、任意のファイルを破壊される恐れがあります。
補足
StringIO と TempFile が区別無しに同じ記述で同じ動作になるのならそうしたいのですが、TempFile になった時だけ print cgi["version"].string というコードで undefined method `string' for #<File:/tmp/CGI20131125-76211-6isjxp-0> というエラーが出て、version の内容を表示させることすらできません。これは何か、別の記述等が必要では無いのでしょうか?