CGI-BBS > CGI > Perl > 画像ファイルをうまくアップロードできない。


カレッヂ
カレッヂ


質問者 fuku  投稿日 2006/8/11(金) 03:47:55
現在1つのCGIで画像をアップロードさせる方法で困っています。
CGIの構成は以下の様になっていて、モードにより各ルーチンに飛ばす方法です。
-----------------------------------------------------------------
#!/usr/local/bin/perl

# フォームデータ取得
	form_data();
# 各ページ出力
	if ( $mode eq "up" ) { up(); }
	html();
──────────────────────
sub form_data
{
# フォームデータ取得
	if($ENV{'REQUEST_METHOD'} eq 'POST') {
		read(STDIN, $query, $ENV{'CONTENT_LENGTH'});
	}
	else {
		$query = $ENV{'QUERY_STRING'};
	}

# フォームデータ復元
	foreach $pair (split(/&/, $query)) {
		($key, $value) = split(/=/, $pair);

		# 文字のデコード
		$value =~ tr/+/ /;
		$value =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr(hex($1))/eg;

		$FORM{$key} = $value;
	}

	$mode = $FORM{'mode'};	#モード
}
──────────────────────
sub up
{
use CGI;

$query = new CGI; 

$filename = $query->param('File');
while(read($filename, $buffer, 2048))
{
	$file .= $buffer;
} 

@files = split(/\\/, $filename);
($basename, $exp) = split(/\./, $files[-1]);

$new_file = $basename . "." . $exp;

# ファイルを指定ディレクトリにコピー 
	open(OUT, "> ./$new_file"); 
	binmode(OUT); 
	print(OUT $file); 
	close(OUT); 

print "Content-type: text/html\n\n";
print "[$basename]  [$exp]\n";
print "正常終了\n";
exit;

}
──────────────────────
sub html
{
print"Content-type: text/html\n\n";
print <<HTML;
<HTML>
	<HEAD>
		<META http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
		<TITLE>アップロード</TITLE>
	</HEAD>
<BODY>
	<FORM method="post" action="i.cgi" enctype="multipart/form-data">
		<INPUT type ="hidden" name="mode" value="up">
		<INPUT size="40" type="file" name="File"> 
		<INPUT type="submit" value="送信する">
	</FORM>
</BODY>
</HTML>
HTML
}
-----------------------------------------------------------------

フォームメソッドがgetの時は、正常終了の表示が出るのですが、
アップロードされた画像が0バイトになり、
フォームメソッドがpostの場合はsub upのルーチンが実行されないようで、
画像はアップロードされず、フォーム入力の画面になってしまいます。

フォーム入力画面をCGIではなく、HTMLにし、CGIには画像アップロード
のプログラム飲みを書いた場合、メソッドをpostにすれば
正常にアップロードできるのですが
この様に1つのCGIにまとめる場合、どうすればいいのでしょうか?

宜しくお願い致します。

【習熟度】多少の設置経験

回答者 rescue  [削除]  投稿日 2006/8/14(月) 10:39:31
フォーム入力画面はHTMLでもCGIで出力しても、どちらも同じはずです。
ブラウザにはどちらもHTMLという形で届き、表示されるわけです。
なので、HTMLのときと、CGI生成で表示されたHTMLのソースを比較し、
何かミスがないかどうか確認してみてはいかがでしょうか?

もうひとつ、GETの場合はクエリー( URL?この部分 )しか送信されませんし、
enctypeをマルチパートに設定しても無視されます。エンコードタイプが
何で送信されてきたかを表示させてみると分かると思います。なので、
POST+マルチパートでないとファイル内容の送信は出来ません。

実際に設置して確認するまでは対応が出来ないのですが、上記のことが何かヒントに
なれば幸いです。

ちなみに、use CGI; はPerl4では使えないので、当サイトの性格上(できるだけ広い環境で使えるCGI)、
私は使ったことがありません。その方法が出来ればスムーズなんですが…。なので、処理としては同じだと
思いますが、私はcgi-lib.plを昔ながらに使っています。これは余談であり、
今回の不具合とは関係ないと思います。


----
サポート掲示板利用ご案内の通り、当方はバグと思われる事象以外には参加しません。
ただ、時間が許す場合に例外的に回答する場合がありますが、継続的にやりとりが
出来ない場合があります。ご理解ください。

なお、この投稿は他の方が別途回答することを妨げるものではありませんので、
私の回答に関係なく、自由に回答をお寄せください。
回答者 Ken  [削除]  投稿日 2006/8/17(木) 17:15:46
はじめまして.
Webアプリケーション開発をおこなっているものです.

まず,グローバルとして使う変数を,
コードの最初にまとめてみてはいかがでしょうか.
あとサブルーチン内では my をつけた方がよいのかな,と感じました.
グローバル変数として利用している $mode がしっかりわたっているかが気になります.
また,up()関数内での変数 $file は初期化されてないですね.
いきなり $file .= xxx  からはじまってるとこに原因があったりするかもしれません.

あと,up()関数のなかで
$q = new CGI; とやっているのならば,
フォームデータ取得のところでもこちらを使うと分かりやすいかと思います.

長々と書いてしまいましたが,お役に立てば幸いです.
質問者 fuku  [削除]  投稿日 2006/8/17(木) 23:39:32
rescue様、Ken様、ご回答有難うございます。
アドバイス通りcgi-lib.plを使用した方法でやってみようかと思います。
フォームデータ取得方法に足りない所があるなど、もっと勉強すべき点がありました。

このページは終了したので返信(回答)は書きこめません
 


Web裏技