• ベストアンサー

CGIの中で異なるContent-typeのファイルを・・・。

CGIでの処理で、今 http://xxxx.com/ok.cgi?id=123&pass=abc&page=index.html でindex.html が表示されているとします。 それで、このindex.htmlから別の拡張子のファイルへリンクさせ、ファイルをダウンロードできるようにしたいと思っています。lzh ならURLはこん感じになります。 http://xxxx.com/ok.cgi?id=123&pass=abc&page=sample.lzh  しかし ok.cgi の最後で print "Content-type: text/html\n"; exit; を指定しているのでリンク先へ行ってもindex.htmlは表示されますが、リンク先のファイルは動きません。 どうすればダウンロード出来るようになるでしょうか? なるべくこのok.cgi の外に出したくないのです。  また、この中で、リンク先が隠れるphpを入れたいと考えましたが、phpも同様に機能しません。これもどのようにすればよろしいでしょうか?  どなたかよろしくお願い致します。

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

  • ベストアンサー
  • taporu
  • ベストアンサー率44% (46/104)
回答No.4

#2です >if($in{'page'} eq "") { $in{'page'} = "index"; } if($in{'page'} eq "") { $in{'page'} = "index.html"; } >open(IN,"./tmp/$tsite/$in{'page'}.html"); open(IN,"./tmp/$tsite/$in{'page'}")||&ErrorNotFile; >print "Content-type: text/html\n\n$buffer\n"; if($in{'page'} =~ /^(.*?)\.html$/){ print "Content-type: text/html\n\n$buffer\n";exit; }elsif($in{'page'} =~ /^(.*?)\.lzh$/){ print "application/x-lzh-compressed\n\n$buffer"; exit; }else{ print "Content-type: text/html\n\n不正なファイルが要求されました。"; } #以下追加 sub ErrorNotFile { print "Content-type: text/html\n\nファイルが存在しません"; exit; } のように変えてください。

senyou2000
質問者

お礼

ありがとうございます。  ダメです....(T^T;)  例えば、改造なしで、最初からlzh を対象とするとして、直接 sample.lzh へ向かうように。  if($in{'p'} eq "") { $in{'p'} = "sample"; }  open(IN,"./item/$tsite/$in{'p'}.lzh");   while(<IN>){$buffer.=$_;}  close(IN);   #省略#  print "application/x-lzh-compressed\n\n$buffer\n"; のみにしておいてもファイルが出てきません。 ダウンロード時に現れるダイアログのファイル名には、 IEではただ「ok」、 オペラでは「ok.cgi」になっており、 「sample.cgi」が出ないのです。    いったいどういう事なのか・・・・。  この場合すぐダイアログが現れるので ブラウザURLの最後に ~sample.lzh 部分がありません。  http://xxxx.com/ok.cgi?id=123&pass=abc  の状態です。  そしてプログラムをいじらないままで、まずindex.htmlへ向かい、そこからsample.lzhへリンクすると ブラウザのURLはきちんと http://xxxx.com/ok.cgi?id=123&pass=abc&page=sample.lzh となっていますが、この場合には今度はダイアログさえ出てきません。  もうなにがなんだか....。

senyou2000
質問者

補足

最初はそのままコピペしたのでlzhのところ Content-type: が抜けていたので表示されなかったようです。その後いろいろやってみましたが、このままだと使えませんね(笑 zip の場合 Content-type: application/zip 及び application/octet-stream で検証。 それぞれダイアログに出てきたファイル名と成否です。 opera: ok.zip (一応ダウンロード出来、ファイルも正常) firefox: ok.cgi IE6: ダイアログなしでいきなりダウンロードでいきなり解凍。一応ファイルは正常たが、探さないとどこに収まったか分からない。どこにあるか分からない為ファイル名は不明。逆に不明だからすぐにはどこにあるか分からない。 lzh の場合 Content-type: application/octet-stream 及び application/x-lzh-compressed で検証。 opera: ok.cgi (ダウンロードしても開かない) fierfox: ok.cgi (ダウンロードしても開かない) IE6: ダイアログなしでいきなりダウンロード。一応ダウンロード出来ていたが、探さないとどこに収まったか分からない。ファイル名はok.lzh php の場合 opera: 表示されない。 Firefox: 表示されない。 IE6: 表示されない。 phpだけでも正常に機能してくれたら、リンク先も見えないのでcgiの外に出すのですが...(泣

その他の回答 (3)

回答No.3

エラーの内容がわからないので、何とも言えないですが、ファイルの読み 取り権限とか、パスの問題のような気がします。パスの場合はフルパスで 指定するとどうでしょうか? else { print $q->header( -type => 'application/octet-stream', -attachment => $page ); # tmpにファイルがあるとして、 my $full_path = '/tmp/' . $page; open my $fh, '<', $full_path or croak "$page: $!"; binmode $fh; my $buffer = ''; while ( read $fh, $buffer, 1024 ) { print $buffer; } close $fh or croak "$page: $!"; } あるいは、次のようにして問題を切り分けするのも手です。次のようにすれば、'Hello CGI'という内容のテキストファイルがダウンロードできます。 else { print $q->header( -type => 'application/octet-stream', -attachment => $page ); print "Hello CGI\n"; } >print $q->end_html; はprint を付けると 1 と言う文字が表示 これは、 >print $q->header( -charset => 'UTF-8' ); のラストを , に変更するに >はしましたが これが原因だと思います。 一つのprint文で済ませたいときは、 print $q->header( -charset => 'UTF-8' ), $q->start_html( -lang => 'ja', -title => ' T I T L E ' ). $q->end_html; として下さい。一つのprint文で済ますのが、一般的かもしれませんね。

senyou2000
質問者

お礼

再度ご教授ありがとうございます。 エラーですが、Internal Server Error と出るだけで、詳しい内容は私も分からないのです。  No,2様のものと平行してこちらも勉強させて頂いています。 実は cgi pm というものをしらなかったので、今さらですが、調べながら触っています。  こちらももう少しテストしていきたいと思います。 ちなみに現状のプログラムはNo,2様の回答欄をご覧下さい。  

senyou2000
質問者

補足

補足覧をお借りしてお礼申し上げます。  別途ある処理の仕方を思いつき、うまくいきました。  お二人様ありがとうございました。

  • taporu
  • ベストアンサー率44% (46/104)
回答No.2

このようなものでは? if($IN{'page'} =~ /^(.*?)\.html$/){ print "Content-type: text/html\n\n"; }elsif($IN{'page'} =~ /^(.*?)\.lzh$/){ print "application/x-lzh-compressed\n\n"; }else{ print "Content-type: text/html\n\n不正なファイルが要求されました。"; } のように、正規表現で分ける。

senyou2000
質問者

お礼

ありがとうございます。 現在いじっているCGIのログイン部ですが、以下のようになっています。 古くに作って頂いたCGIで、それに手をくわえたいと思っていました(作った人は今連絡が取れない)。 昨日からお教えいただいたものを入れようとしましたが、わたしの知識不足で、挫折ぎみです。 お手数ですが、以下の場合どのように手を加えれば宜しいでしょうか? #ok.cgi  ログイン部分 ####################### sub login { if($in{'page'} eq "") { $in{'page'} = "index"; } # tmp以下に入れるとしています。 open(IN,"./tmp/$tsite/$in{'page'}.html"); while(<IN>){$buffer.=$_;} close(IN); $buffer =~ s/<!--id-->/$in{'id'}/ig; $buffer =~ s/<!--passwd-->/$in{'pass'}/ig; # 諸事情から ~.ok.cgi?id=<!--id-->&pass=<!--passwad-->&page=index となっています。 # 別に ?id=$id&pass=$pass でいいと思いますが・・・。それはそれとして・・・。  print "Content-type: text/html\n\n$buffer\n"; exit; } ######################### よろしければ再度ご教授下さい。

回答No.1

GETパラメータで処理を分ければいいんじゃないかなあ #!/usr/bin/perl -T use warnings; use strict; use utf8; use CGI; use CGI::Carp qw(fatalsToBrowser); use CGI::Pretty; my $q = CGI->new(); my $id = $q->param("id"); my $pass = $q->param("pass"); my $page = $q->param("page"); if ( $page eq 'index.html' ) { print $q->header( -charset => 'UTF-8' ); print $q->start_html( -lang => 'ja', -title => ' T I T L E ' ); print $q->end_html; } else { print $q->header( -type => 'application/octet-stream', -attachment => $page ); open my $fh, '<', $page or croak "$page: $!"; binmode $fh; my $buffer = ''; while ( read $fh, $buffer, 1024 ) { print $buffer; } close $fh or croak "$page: $!"; }

senyou2000
質問者

お礼

ありがとうございます。  どうもうまくいきません。 print $q->header( -charset => 'UTF-8' ); のラストを , に変更するにはしましたが、その後 else{ } を入れた段階でエラーになってしまいます。  ところで print $q->end_html; はprint を付けると 1 と言う文字が表示されてしまうので、purint は要らないと思って良いのですよね?  うまくいかないのは何が原因でしょうか?