D01:ファイルを転送する
CGIで凝ったものを作り始めると、ローカルにあるファイルを送りたい事もあると思います。
今回は、ファイルを転送するようなCGIを紹介します。
ただし、ファイルを受け取るCGIを作る場合、サイズが大きいファイルを送られる可能性がある事に注意して下さい。
ファイルを開く
解説
#!/usr/local/bin/perl
プロバイダがPerlを置いている場所を記述します。
ここでは/usr/local/bin/perlにあるとしています。
$max=2;
送られてくるデータの数を$maxに代入しています。
データはファイル以外も可能です。
$size=$ENV{'CONTENT_LENGTH'};
送られてきたデータのサイズを$sizeに代入しています。
ただし、複数のデータが決まったフォーマットに従ってまとめて送られてくる為、実際にはデータ本体以外の部分も合わせたサイズになっています。
if($size>1024*1024){
exit;
}
送られてきたデータのサイズが1MBより大きい場合にはプログラムを終了しています。
送られてきたデータがあまりにも大き過ぎると色々と不都合があるので、ここでは1MBに制限しています。
☆今回のポイント☆
ファイルを受け取る時はサイズに気を付けよう!
binmode(STDIN);
送られてくるファイルの種類を特に決めていないので、バイナリデータとして扱う為にbinmode(STDIN)を書いています。
while($size){
$len=sysread(STDIN, $buf, $size);
if($len==0){
last;
}
$size=$size-$len;
$data=$data.$buf;
}
送られてきたデータを$dataに代入しています。
$x=index($data,"\r\n");
$cut=substr($data,0,$x);
$cut="\r\n".$cut;
複数のデータが送られてくる場合、特定の文字列で区切られています。
その区切りの文字列を$cutに代入しています。
for($i=0;$i<$max;$i++){
$x=index($data,"\r\n\r\n")+4;
$filename[$i]=substr($data,0,$x);
$filename[$i]=~s/\n//g;
$filename[$i]=~s/.*filename="//;
$filename[$i]=~s/".*//;
$filename[$i]=~s/.*\\//g;
$filename[$i]=~s".*/""g;
$y=length($data);
$data=substr($data,$x,$y-$x);
$x=index($data,$cut);
$y=length($data);
$file[$i]=substr($data,0,$x);
$data=substr($data,$x+2,$y-$x-2);
}
$maxの数だけ送られてきたデータを$file[xx]に代入しています。
データがファイルの場合はファイル名が$filename[xx]に代入されます。
xxに入る数字は0〜$max-1の数字になります。
binmode(STDOUT);
出力するデータをバイナリ形式で扱うのでbinmode(STDOUT)を書いています。
print "Content-type:application/octet-stream\n";
print "Content-Disposition:attachment;filename=$filename[0]+$filename[1]\n\n";
出力するデータがダウンロードする形式である事を出力します。
print $file[0];
print $file[1];
送られてきた2つのファイルを続けて出力しています。
exit;
プログラムを終了させます。