ようこそ ゲスト さん、新規登録(無料)して気になる疑問を解決しませんか?

質問

QNo.4168949 cgiでデータのDL直後にメッセージを出したいのですが
質問者:kaduno 自宅サーバーを運用していて、つまづいております…

私のサーバーでは、データへはURLでは直接アクセスさせないで、cgiの中で
文字列を置換して、HDDの中のフォルダ名/ファイル名を指定して、DL
させるようにしています。
(事情があり、この方法にしております)

そこで、DL時のダイアログを表示させる為に、以下のような2つのcgiを
作成して、cgi_aの"DLボタン画像"を左クリックすると、cgi_bへジャンプ
して、実データをクライアントのPCに保存出来るようになっております。

ここで、DL後にメッセージを表示させるようにしたいのですが、
cgi_bで『Content-type: application/download』としてしまっている為に
メッセージを表示させたくても、html記述が出来ずに困っております。

『Content-type: application/download』の後に、
『Content-type: text/html』に戻せるような方法や、その他html記述が
出来るような解決方法をご存知のかたがいらっしゃいましたら、よろしく
お願いします。



<元のcgi(cgi_aと命名)>

print "Content-type: text/html\n\n";
print <<"---HTML---";
<html><head><title></title></head>
<div align="center">
<form action="ジャンプ先のcgi" method="POST" name="entry">
<tr>
<input type="hidden" 渡すパラメータの記述が数個 >
<td><input type="image" src="DLボタン画像.gif" value="submit" onclick="this.entry.submit(); return false;" /></td><BR>
<BR>


<ジャンプ先のcgi(cgi_bと命名)>

print "Content-type: application/download\n";
print "Content-Disposition: attachment; filename=$filename\n\n";

binmode(STDOUT);
open(DATA,"$value") ;
binmode(DATA);
print <DATA>;
close(DATA);
困り度:
  • 困っています
質問投稿日時:
08/07/11 20:18
この質問に対する回答は締め切られました。

回答良回答10pt

ANo.2 いろいろやってみたのですがどうやらファイルのダウンロードをすると
onloadは効かないようですね。
なので、どうしてもダウンロードを待ってページの推移を行うって
できそうにないのですが...。

力不足ですみません。

> ネット回線の速度を測定するHPでは、データをDL後に次の処理に進まないと、速度を表示出来ないのだと思いますけど、そのページのように
> 完全にDLが終わってから、メッセージを表示させたいと思っております。

その用途だと回線速度を計測するためだけにファイルをDLしたいと
いうことでしょうか。
ファイルを実際にローカルに保存する必要がないようならAjaxを
使用すればできそうな気がしますがあいにくAjaxはよく分からないので
サンプルを作れません。
回答者:pick52
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:
08/07/15 23:21
この回答へのお礼こんにちは、

>力不足ですみません。

いえ、ありがとうございます。

>回線速度を計測するためだけにファイルをDLしたいということでしょうか。

説明がヘタですいません。
DLが完全に終わってから、次の処理へ  という意味を強調したかっただけでして。

ホント、いろいろ試して戴いて有り難うございました。

回答

ANo.1 普通にはできないのでこんな感じでフレームを使用して無理矢理実現
するのはどうでしょうか。

use strict;
use CGI::Carp qw(fatalsToBrowser);
my $cgi = &getreq();

# リクエストにより処理を分岐する
if($cgi->{'mode'} eq 'main') {
&main();
} elsif($cgi->{'mode'} eq 'dl') {
&dl('test.cgi');
} elsif($cgi->{'mode'} eq 'comp') {
&comp();
}

# フレーム表示
&header('テスト', 1);
print <<"HTML";
<frameset rows="100%,0%">
<frame src="./test.cgi?mode=main" frameborder="0" name="main" noresize>
<frame src="about:blank" frameborder="0" name="hide" noresize>
</frameset>
HTML
&footer();
exit;

# CGI リクエスト取得
sub getreq {
# 環境変数取得
my $cgi = {};
my $query = '';
read(STDIN, $query, $ENV{'CONTENT_LENGTH'}) if($ENV{'CONTENT_LENGTH'});
$query = join('&', $query, $ENV{'QUERY_STRING'});

# デコード
my @args = split(/&/, $query);
foreach my $i (@args) {
my ($name, $val) = split(/=/, $i);
$val =~ tr/+/ /;
$val =~ s/%(\w{2})/pack('C', hex($1))/eg;
$val =~ s/(\x0d0a|\x0a|\x0d)+$//;
$name =~ tr/+/ /;
$name =~ s/%(\w{2})/pack('C', hex($1))/eg;
$name =~ s/(\x0d0a|\x0a|\x0d)+$//;
if(exists($cgi->{$name})) {
$cgi->{$name} = [(ref($cgi->{$name}) eq 'ARRAY' ? @{$cgi->{$name}} : $cgi->{$name}), $val];
} else {
$cgi->{$name} = $val;
}
}
delete($cgi->{''});

return $cgi;
}

# HTTP ヘッダと HTML ヘッダ
sub header {
my $title = shift;
my $body = shift;
print "Content-type: text/html; charset=shift_jis\n\n";
print <<"HTML";
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
<meta http-equiv="content-type" content="text/html; charset=shift_jis">
<title>$title</title>
</head>
HTML
print "<body>\n" unless($body);
return;
}

# HTML フッタ
sub footer {
print "</body>\n</html>\n";
exit;
}

# メインページ
sub main {
&header('テスト');
print <<"HTML";
<form action="test.cgi" method="post" name="entry">
<input type="button" value="submit" onclick="top.hide.location.href='test.cgi?mode=dl';location.href='test.cgi?mode=comp';">
</form>
HTML
&footer();
}

# ファイル DL
sub dl {
my $fn = shift;
print "Content-disposition: attachment; filename=$fn\n";
print "Content-type: application/octet-stream\n\n";
if(open(FILE, '<test.cgi')) {
print <FILE>;
close FILE;
}
exit;
}

# コンプリート画面
sub comp {
&header('DL 完了!!');
print "<div>ダウンロード完了!!</div>\n";
&footer();
}

1;

これだとフレームに非対応なブラウザなどで正常に動作しませんが。
(実際には<noframes>を忘れないようにしてください)
回答者:pick52
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:
08/07/13 04:28
この回答へのお礼こんにちは。

『CGI リクエスト取得』『デコード』など、私のレベルでは難しくて分からないところもありますが、それでも『ファイル DL』のサブルーチンで
ファイル名を設定してDL出来るまでにはなりました。

このプログラムは、メインページで『test.cgi』に『mode=dl』と『mode=comp』と同時に送っているのですよね。

この同時というものが厄介でして、ちょっと大きめのデータをDLしようとしたところ、DL完了前に『ダウンロード完了』のメッセージが出て
しまいました。

ネット回線の速度を測定するHPでは、データをDL後に次の処理に進まないと、速度を表示出来ないのだと思いますけど、そのページのように
完全にDLが終わってから、メッセージを表示させたいと思っております。