WEB相談室

Webページ作成に関しての何でも掲示板です。

タイトル:写真アップロードCGI

0:[投稿] ゆいちゃん [MAIL] [2002/04/11 16:53 ][環境:WIN+IE WIN系+Perl]

現在、自宅サーバ(Windows)上で
ユーザPCから自宅サーバに写真をアップロードするCGI
を作成しようとしています。
サンプルを探しているのですが経験不足のため
思うように探せません。
どなたか良いサンプルを知っている方は
教えてください。
よろしくお願いします。
(できればシンプルでわかりやすいものがいいです。)


1:[回答] のぐりん [MAIL] [2002/04/11 17:01 ]

以前、偶然に見つけたHPです。

http://naha.cool.ne.jp/c_p_yuu/tec/1-2.html

#私は、Perlの経験がほとんどないので、動作の説明は出来ませんが、、、
#ASP用のファイルアップロードを探していたときに見つけたものです。Perlだったので、お気に入りに入れただけでした。


2:[回答] えび [2002/04/11 17:21 ]

 CGI.pm を使うと楽だと思います。

use CGI;
$form = New CGI;
$fh = $form->upload('control_name');
print FOO while(<$fh>);

 とかいう感じでできてしまいます。詳しくは、
http://member.nifty.ne.jp/hippo2000/perltips/Cgi.htm
 の「ファイルアップロードフィールド」を参照しつつ……。

 CGI.pm は標準モジュールなのですが、古い CGI.pm だと upload メソッドが実装されいないので注意が必要です。


3:[回答] てらちゃん [MAIL] [2002/04/14 14:35 ]

えびさんこんにちわ
返事が遅れてすみません。
はじめてCGI.pmというのを聞いたので
「詳しくは、・・・」というのを見て
使用しようと思ったのですが
取り付け方法とか、使用方法とか
よくわかりまでした。
そこでダウンロードのページに行って
見たのですが
http://stein.cshl.org/WWW/software/CGI/
英語ばっかりで・・・
結局ダウンロードしただけで、お手上げでした。
こんなに簡単にファイルのアップロードできるなら
ぜひ、使ってみたいのですが、
よろしければ、設置方法など教えてください。
また、現在、PERLでプログラムを組んでいるのですが
ファイルのアップロードの時だけCGI.pmを使用
するのって可能ですか?


4:[質問] てらちゃん [MAIL] [2002/04/14 14:36 ]

えびさんこんにちわ
返事が遅れてすみません。
はじめてCGI.pmというのを聞いたので
「詳しくは、・・・」というのを見て
使用しようと思ったのですが
取り付け方法とか、使用方法とか
よくわかりまでした。
そこでダウンロードのページに行って
見たのですが
http://stein.cshl.org/WWW/software/CGI/
英語ばっかりで・・・
結局ダウンロードしただけで、お手上げでした。
こんなに簡単にファイルのアップロードできるなら
ぜひ、使ってみたいのですが、
よろしければ、設置方法など教えてください。
また、現在、PERLでプログラムを組んでいるのですが
ファイルのアップロードの時だけCGI.pmを使用
するのって可能ですか?


5:[回答] えび [2002/04/14 16:34 ]

 CGI.pm は Perl5 の標準モジュールです。通常の Perl5 が動く環境であれば、インストールしなくても使えます(最初からインストールされている)。
 もっとも、@nifty のようにモジュール類が全くないところがあったりしますし、Perl5 でも古いものだと CGI.pm 自体が古く、upload メソッドをサポートしていないことがあります。そんな場合は自ら CGI.pm を設置する必要があります。

 とりあえずは、何も考えずに use CGI; したスクリプトを書いて、動作するかどうか試してみると良いと思います。新しめの Perl5 が動いているなら、そのまま動いてしまうはずです。


6:[質問] てらちゃん [MAIL] [2002/04/16 01:04 ]

えびさんご回答ありがとうございます。
何回も申し訳ありません。また質問させてもらってもよろしいでしょうか?
えびさんの言うように何も考えずに
以下のようにしてuser CGI;して動作確認してみました。

$pict = "$photo_asp$FORM{'user'}_$FORM{'passwd'}.gif";    
open(PICT,">$pict");
   use CGI;
   $form = New CGI;
   $fh = $from->upload($FORM{'upfile'});
   print PICT while(<$fh>);
close(PICT);

上記のようにしたのですが、内部サーバーエラーになってしまいました。
そこで

$pict = "$photo_asp$FORM{'user'}_$FORM{'passwd'}.gif";    
open(PICT,">$pict");
   use CGI;
#    $form = New CGI;
#    $fh = $from->upload($FORM{'upfile'});
   print PICT while(<$fh>);
close(PICT);

という風にコメントにして実行したところ
ファイルは正しく作成されました(中身はありません)。
そこで、

$pict = "$photo_asp$FORM{'user'}_$FORM{'passwd'}.gif";    
open(PICT,">$pict");
   use CGI;
   $form = New CGI;
#    $fh = $from->upload($FORM{'upfile'});
   print PICT while(<$fh>);
close(PICT);

として実行してみると内部サーバーエラーになってしまいました。
New CGIを呼び出してエラーになるということはCGI.pmをサポートしていないのでしょうか?
現在使用しているPerlはActivePerl-5.6.1.631-MSWin32-x86.msiです。
それと、upload('control_name');
control_nameのとこにはupload($FORM{'upfile'});
という風に記入していいのでしょうか?

ご迷惑をおかけします。


7:[回答] ふじ [URL] [2002/04/16 02:39 ]

New じゃなくて new (すべて小文字) では?


8:[回答] えび [2002/04/16 13:51 ]

 良いのでしょうかと言われても、$FORM{'upfile'} に何が入っているのか分からないのでなんとも言えないのですが、INPUT要素の name 属性の値をそのまま入れておけば OK です。
 ちなみにファイルアップロード以外のパラメータも

$name = $form->param('control_name');

 などとして拾えます。


9:[回答] jam [2002/04/16 17:03 ]

>$fh = $from->upload($FORM{'upfile'});
$fh = $from->upload('upfile');
かと・・・


10:[質問] てらちゃん [MAIL] [2002/04/16 23:31 ]

みなさんご面倒おかけします。
大文字と小文字を認識しているのですね。
ふじさんありがとうございます。
jamさんのいうとおりでした。
jamさんありがとうございます。
でも、ファイルをアップロードできません。
えびさんの教えてくれた
$name = $form->param('upfile');
で値を取得してみたら、
D:\photo\test.gif
で正しく取得できているのですが・・・
画像ファイルがダメなのかと思いテキストファイルでも
試みましたがダメでした。
「upload()はファイルハンドル、もしくはパラメータが正しいファイルハンドルでなければundefを返します。」
ということで調べてみたら、upload()には何も入っていなかったのでOK??
最終的には以下のようになりました。
    $pict = "$photo_asp$FORM{'user'}_$FORM{'passwd'}.gif";
    open(PICT,">$pict");
    use CGI;
    $form = new CGI;
    $fh = $form->upload('upfile');
    print PICT while(<$fh>);
    close(PICT);
ファイル自体は中身なしで作成されます。
なぜでしょう?
よろしくお願いします。


11:[回答] ふじ [URL] [2002/04/17 03:10 ]

もしやと思いますが、<form> に、enctype="multipart/form-data"
を指定していますか?
# method="POST" も。

指定しないと、$form->param('upfile') でファイル名は取得できますが、
$form->upload('upfile') は undef が返ります。
実際のファイルの内容は送られていないので。


12:[質問] てらちゃん [MAIL] [2002/04/17 14:57 ]

enctype="multipart/form-data"は指定していますが
method="POST" ではなく "GET" を使用しています。
自宅サーバでhttpdを使用する場合 "GET"でないと
動かなかったので・・・
"POST"にすると内部サーバエラーが発生します。
$form->upload('upfile')
は使用できないのでしょうか?
一応、formの内容を最後に記載します。
それと$form->upload('upfile')は正常値は何を返すのでしょうか?現在の時点で $form->upload('upfile') = "" でした。

     <FORM method="$method" action="$script_photo" enctype="multipart/form-data">
     <input type=hidden name=mode value="upd_photo">
     <input type=hidden name=user value="$FORM{'user'}">
     <input type=hidden name=passwd value="$FORM{'passwd'}">
     <INPUT size="30" type="file" name="upfile"><BR>
     <BR>
              <INPUT type="submit" name="btn_upd" value="登録"><BR>
     </FORM>

よろしくお願いします。


13:[回答] ふじ [URL] [2002/04/17 15:25 ]

GET で送信できるサイズは最大数KB程度なので、画像などのファイルをアップロード
するには POST を使用する必要があります。

> "POST"にすると内部サーバエラーが発生します。
エラーログを見ましょう。原因が書いてあるはずです。

> それと$form->upload('upfile')は正常値は何を返すのでしょうか?
ファイルハンドルを返します。



14:[質問] てらちゃん [MAIL] [2002/04/17 21:04 ]

"GET"で試してみたところ
httpdのエラーログにはなにも書かれていませんでした。
"POST"で試してみたところ
Wed Apr 17 19:48:40 2002 Error Response 500 Thread 0(ID= 300) to 127.0.0.1 for "/cgi/photo/photo.cgi"
というようなエラーが書かれていました。
httpdはWindows環境ではPOSTをサポートしていないらしく
現在、httpdの作成者にPOSTを本当に使用できないのか相談しています。
それと

>$form->upload('upfile')は正常値は何を返すのでしょうか?
ファイルハンドルを返します

ということですが
ファイルハンドルということは何か文字列が入っているということに
なると思うのですが、
現在の段階(GETを使用)では、
$form->upload('upfile')は何も入っていません。
これもPOSTを使用することによって原因を解消できるのでしょうか?

よろしくお願いします。


15:[回答] ふじ [URL] [2002/04/17 21:22 ]

> httpdはWindows環境ではPOSTをサポートしていないらしく
> 現在、httpdの作成者にPOSTを本当に使用できないのか相談しています。
単に「httpd」というと、HTTPサーバソフト一般を指すことが
多いと思いますので、なんというソフトなのかちゃんと書いたほうがよろしいかと。

> これもPOSTを使用することによって原因を解消できるのでしょうか?
私の環境の Mozilla 0.9.8 (Linux) では、
enctype="multipart/form-data"
method="GET"
と指定した場合は POST で送信されました。

IE6.0(Windows2000) では、同様の記述の場合 GET で送信され、
エンコードは通常の(何も指定しない場合と同じ)形式でした。
# ここらへんの挙動はUAによって異なるのかも。

ともあれ、ファイルアップロードするには POST が使えることが
必須だと思います。


16:[保留] てらちゃん [MAIL] [2002/04/17 22:17 ]

すみません。
中田昭雄氏制作のAN HTTPDです。
httpdというとこれのことかと思っていいました。
環境はwindows ME(本番環境) と XP(テスト環境) です。

>ともあれ、ファイルアップロードするには POST が使えることが
>必須だと思います。

そうですか。困っちゃいました。
とりあえずは、POSTが使えるようになることですね。
POSTが使えるようになったら、またここに連絡します。
そのときは、よろしくお願いします。


17:[回答] jam [2002/04/18 13:26 ]

>中田昭雄氏制作のAN HTTPDです。
実験しましたがアップロード出来ました。
実験環境
WinNT4.0
AN HTTPD var1.33e


18:[回答] ゆいちゃん [MAIL] [2002/04/18 23:33 ]

jamさん、この間はありがとうございます。
>実験しましたがアップロード出来ました。
>実験環境
>WinNT4.0
>AN HTTPD var1.33e
とのことですが、そうなんですか?
私の環境は、
Windows XP
AN HTTPD var1.37d
ですが、WinNTがアップロードできるならXPでも
できそうなのですが・・・
以前、中田昭雄氏に相談したところ、
WindowsXp に限らず、
AN HTTPD はHTMLファイルのPOSTメソッドを受けつけない
という風に返答がありました。
一応、その時のやり取りが以下に記載してあります。
http://homepage1.nifty.com/yito/namazu/gbook/20020404.0033.html
今後ともよろしくお願いします。


19:[回答] jam [2002/04/19 09:28 ]

>http://homepage1.nifty.com/yito/namazu/gbook/20020404.0033.html
上記のやり取りではPOSTできないって言ってますね^^;

でも、AN HTTPのHPのHistoryでは以下の記述かありますけど・・・
>ファイルアップロードなどバイナリや64kB以上のファイルの POST の不具合を直しました。

でもバージョン番号が1.22cとなっています、
そこで私が試したバージョンがvar1.33e、
ゆいちゃんのバージョンがvar1.37dで新しいですよね、
var1.33eからvar1.37dの間にPOSTが廃止になったんですかね??
あいにくHistoryは、[1.33g] 01/5/7 の記述までしかないので、
わかりませんが・・・
そこいらへんを、中田昭雄氏に聞いてみてはいかがでしょうか?


20:[回答] たこすけ [2002/04/19 10:07 ]

http://homepage1.nifty.com/yito/namazu/gbook/20020404.0033.html
> $homepage = "http://127.0.0.1/f_top_main.html"
> <FORM method="$method" action="$homepage">

から察するに
> HTMLファイルのPOSTメソッドを受けつけない
というのは
HTMLファイル「へ」のPOSTメソッドを受けつけない
という意味では?

拡張子を html では無く cgi にしてみてはどうでしょう。


21:[回答] えび [2002/04/19 13:11 ]

 HTML の POST というのは、「POST メソッドで HTML を呼ぶ」という話と思われます。POST メソッドで HTML を呼び出そうとすると Method Not Allowed で蹴られるというのは普通の動作です。Apache でもそうなると思います。

 AnHTTPd で動作する CGI が POST を受け付けない、という訳ではないはずです。そもそも CGI が POST を受けなかったら CGI のテストなどできた物ではありません。


22:[回答] しなのむし [2002/04/19 13:37 ]

var1.37dで

拡張子htmlのファイルに対してPOSTした場合
HTTP/1.1 501 Not Implemented

拡張子cgiのファイルに対してPOSTした場合
HTTP/1.1 200 Document follows


23:[関連] えび [2002/04/19 14:49 ]

 POSTメソッド自体が実装されてないならともかく、そうでもないのに 501 を返すのはどうかと思いました。405 がベター、せめて 400 でしょう。
 って完全に話がずれていますが。


24:[回答] ゆいちゃん [MAIL] [2002/04/19 16:15 ]

最初に、お礼を・・・
皆さんどうもご親切に、本当にありがとうございます。

http://homepage1.nifty.com/yito/namazu/gbook/20020404.0033.html
で確認した内容はCGIファイルからHTMLファイルを呼び出す
というものでしたが、写真をアップロードするときは、
CGIからCGIを呼び出す動作でしています。

えびさんが教えてくれたこと
>AnHTTPd で動作する CGI が POST を受け付けない、という訳ではないはずです。
>そもそも CGI が POST を受けなかったら CGI のテストなどできた物ではありません。

以前、BIGLOBEのホームページ領域を使用していたときは、
CGIからHTMLを呼び出すときはformを使用してPOSTでもいけたのですが、
Windowsでan httpdを使用していると<A href>を使用しなければならないということですか?

しなのむしさんが教えてくれたこと
>var1.37dで
>拡張子htmlのファイルに対してPOSTした場合
>HTTP/1.1 501 Not Implemented
>拡張子cgiのファイルに対してPOSTした場合
>HTTP/1.1 200 Document follows
はhtmlファイルは実行できなくて、CGIファイルは実行できた。
ということを意味しているのですね?

試しに他のCGIで試してみました。(POSTでCGIからCGIを呼び出す)
そうすると確かに正常に動きました。
ということは私の記述に問題があるということですね。

一応、写真アップロードCGIファイルの内容は以下に記載します。

FORM内容は
    $script_photo = "./photo.cgi";
    <FORM method="$method" action="$script_photo" enctype="multipart/form-data">
    <input type=hidden name=mode value="upd_photo">
    <input type=hidden name=user value="$FORM{'user'}">
    <input type=hidden name=passwd value="$FORM{'passwd'}">
    <input size="30" type="file" name="upfile"><BR>
    <input type="submit" name="btn_upd" value="登録">
    </FORM>
です。
実行するときの内容は
    $photo_asp = "../../gif/photo/";
    sub upd_photo{
        $pict = "$photo_asp$FORM{'user'}_$FORM{'passwd'}.gif";
        open(PICT,">$pict");
        use CGI;
        $form = new CGI;
        $fh = $form->upload('upfile');
        print PICT while(<$fh>);
        close(PICT);
        # 写真登録完了メッセージの表示
        &end_mes("写真を登録しました。");
        exit;
    }
です。

現時点でこれを実行すると
$method = 'POST'の時は
    HTTP 500 - 内部サーバー エラー
$method = 'GET'の時は
    ファイルは指定の場所に作成されるが、0ファイルで作成される。

とりあえず、POSTにして内部サーバエラーを出さないよう動かさなければ
ならないようなのでがんばります。


25:[回答] ゆいちゃん [MAIL] [2002/04/19 18:05 ]

現在、内部サーバエラーがどうして出るのか
を調査していますが、あることに気づきました。
POSTにしてFORMのenctype="multipart/form-data"を指定すると
内部サーバエラーが出るようです。
POSTにしてenctype="multipart/form-data"を指定しないと
内部サーバエラーにはなりません。
相変わらず、アップロードされた写真は、0ファイルのままです。
どういうことでしょう?


26:[回答] ふじ [URL] [2002/04/19 19:39 ]

CGI.pm はアップロードされたファイルをテンポラリファイルに
保存するのですが、そのテンポラリファイルを書き込む場所(ディレクトリ)がない、
もしくは書きこむ権限がない、のかも知れません。
# エラーログにその原因が出ていそうなものですが・・・

http://member.nifty.ne.jp/hippo2000/perltips/Cgi.htm
を参照。

AnHTTPD で環境変数を設定できるなら、TMPDIR を適当なディレクトリに
設定するか、C:\temp というディレクトリを作って、CGIのプロセスから
書き込み可能なように適切な権限を与えてみては。


27:[回答] ゆいちゃん [MAIL] [2002/04/19 21:23 ]

ふじさん、ご回答ありがとうございます。
CGI.pmdでテンポラリを使用する場合
use CGI qw(-private_tempfiles);
と記載して C:\tempを作成すれば
よいのでしょうか?
一応これで実行してみましたが、結果は同じでした。

>AnHTTPD で環境変数を設定できるなら、TMPDIR を適当なディレクトリに
>設定するか、C:\temp というディレクトリを作って、CGIのプロセスから
>書き込み可能なように適切な権限を与えてみては。
ということですが、AnHTTPDではtmpDIRは強制的にwwwルート
にできてしまうようです。
http://homepage1.nifty.com/yito/namazu/gbook/20011122.1359.html
記事が去年なので現在のバージョンではできるかどうかわかりませんが・・・

それと
># エラーログにその原因が出ていそうなものですが・・・
エラーログとはAnHTTPDのログのことでしょうか?
エラーログにはなにも書かれておらず、
正常終了しているようです。
う〜どうしよう・・・・
また、よろしくお願いします。



28:[完了] ゆいちゃん [MAIL] [2002/05/17 12:02 ]

最初に返事が送れたことをお詫びします。
引越しで1ヶ月ほどネットが見れなかったのです。
写真アップロードの件はどうにか完了しました。
結局、初期処理が悪さをしていたことはわかりましたが
詳しくは、よくわかりませんでした。
初期処理は以下です。
# 初期処理(デコード)
sub cmn_decode {
  if ($ENV{'REQUEST_METHOD'} eq "POST") {
    read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
  } else { $buffer = $ENV{'QUERY_STRING'}; }
    @pairs = split(/&/, $buffer);
    foreach $pair (@pairs) {
    ($name,$value) = split(/=/, $pair);
    $value =~ tr/+/ /;
    $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

    # 文字コード変換 (Shift-JISコード)
    &jcode'convert(*value,'sjis');
    # タグ禁止処理
    $value =~ s/</&lt;/g;
    $value =~ s/>/&gt;/g;
    $value =~ s/,/&#44;/g;
    $FORM{$name} = $value;
  }
}
これをすることにより
POSTにしてFORMのenctype="multipart/form-data"を指定すると
内部サーバーエラーが出るようです。わかる方がいれば
教えていただけたらうれしいです。
そして、実際に写真をアップロードしたコードは以下です。
# アップロード
sub upload{
  use CGI qw (:standard);
  use CGI::Carp qw(fatalsToBrowser);
  my $file_name   = param('filename');
  my $data;
  my $mime      = uploadInfo($file_name)->{Content-Type};
  open (STORAGE, ">$cmn_photo")
    || &error("ファイルOpen: $cmn_photo_asp");
  if($mime !~ /text/){
    binmode ($file_name);
    binmode (STORAGE);
  }
  while( read($file_name, $data, 1024) ){
    print STORAGE $data;
  }
  close STORAGE;
}

最後に、えびさん、ふじさんをはじめ多くの方、ありがとうございました。
今度は、回答の方にもちょこちょこ顔を出しますのでよろしくお願いします。
質問の方が多いかも・・・

回答(必須): 状態:

お名前(必須):

e-mail:

URL:




[戻る]

ChaichanPAPA's World