CGI.pmのアップロード後のファイル処理を高速に行う
とりあえず手っ取り早くファイルアップローダを作らなくちゃならなくなったとき用の汎用ルーチンとしてCGI.pmを使ったアップローダのソースをあげておこうと思いました。自分用のメモだけど単純にアップロード後の処理が高速なので参考にされるといいかと思います。
fillename:upload.cgi
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use CGI::Carp qw(fatalsToBrowser);
use File::Copy;
use File::Basename;
my $upload_dir = 'upload'; # 保存先のディレクトリ
my $q = CGI->new(); # CGIオブジェクト
my $fh = $q->upload('filename'); # ファイルハンドル兼ファイル名
my $temp_path = $q->tmpFileName($fh); # アップロードされた
#ファイルのフルパス
fileparse_set_fstype('MSDOS'); # WinIE用パス文字設定
my $filename = basename($fh); # アップロードされたファイルの
# ファイル名
my $upload_path
= "$upload_dir/$filename"; # 保存先フルパス
move ($temp_path, $upload_path) # File::Copy の moveメソッドで
or die $!; # 移動
close($fh); # おまじない
print $q->header( -type=>'text/html', -charset=>'UTF-8', );
print <<"END_OF_HTML";
<body><p>done.</p></body>
END_OF_HTML
exit;
__END__
filename: upload.html
<html>
<body>
<form action="upload.cgi" method="post"
enctype="multipart/form-data">
<p>
<label for="filename">file</label>
<br>
<input type="file" name="filename" id="filename">
</p>
<p>
<input type="submit" name="submit" value="submit">
</p>
</form>
</p>
</body>
</html>
~~~
よく、CGI,pmによるアップローダの説明で、
:: Cepheid :: - ファイルのアップロード その1
# ファイル取得
my $fH = $query->upload('filename');
# MIMEタイプ取得
my $mimetype = $query->uploadInfo($fH)->{'Content-Type'};
# ファイル保存
open (OUT, ">Savefile") || die "Can't open Savefile!";
binmode (OUT);
while(read($fH, $buffer, 1024)){
print OUT $buffer;
}
close (OUT);
close ($fH) if ($CGI::OS ne 'UNIX'); # Windowsプラットフォーム用
なんてコードを見ますけれども、いまどき印刷業界は1GB超のファイルも平気で飛び交うのですから、これはかなり効率が悪い。ガソリンスタンドでしょうゆちゅるちゅるを使っているような感覚です。
次に、
ファイルアップロードの仕方 [www.hidekik.com]
my $fh = $q->upload('upfile');
copy ($fh, "$newfile");
close($fh);
ですが、なるほどFile::Copy [search.cpan.org] モジュールのcopyメソッド、これは頭がいいなーと思うわけですけれども、これとて1GBのファイルだったりしたら、アップロード済みのテンポラリファイルから、アップロード先へのベタコピーをしているわけで、なんだか無駄っぽいです。実際ユーザから見ると、アップロードが終わってから何10秒も待たないと処理が終わらないわけです。
つうわけで、普通にmoveメソッドでやっちゃえばいいってことになります。
そして、アップロード済みで、廃棄予定のテンポラリファイルのファイル名を
$q->tmpFileName($q->upload('filename') )
で取れてしまうこともポイント。これにより、簡単にmoveできるようになりましたとさ。これ探り当てるまで3年かかっている。そのあいだ、アップロードファイルが直接対象ディレクトリに保存される、CGI::Liteモジュール使っていたわけです。長くかかったねー
moveなので、同じファイルシステム上にあれば、高速に処理が終わりますので、とてもいいと思いますがいかがでしょうか。
※アップロードされたファイルのファイル名の取り扱いについては、また変なノウハウがいるので今回は割愛。
M.C.P.C.: CGI.pmのuploadメソッドでファイル名取得したらフルパスからファイル名を取り出す処理を入れる
M.C.P.C.: Safari の ファイル送信フォームのファイル名のデコード
トラックバック
この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/19018/16698465
この記事へのトラックバック一覧です: CGI.pmのアップロード後のファイル処理を高速に行う:
コメント
ファイルアップロードのCGIを参考にさせていただきましたが、残念なことにうまく動きませんでした。
Windows 2003 Server // IIS // Perl 5.8使用で、moveの時点で dieが発生します。
どうも、cgi.pmがファイルを掴んだままなのか「Permission denied」のエラーが出てしまいますね。
IISのスクリプト実行ユーザーをAdministrator権限のユーザーでテストしてみましたが同じでした。
ファイルのアクセス権に関しての設定は問題無いので、moveを、copyにすれば問題無く処理が完了します。
しかしながら、copyだと・・・・( ^^) _旦~~
投稿者: すずめちゃん (2009/02/26 16:59:20)
すずめちゃん さん:
[Perl] CGI.pm の TMPDIRECTORY isoya9の日記/ウェブリブログ
にある、一時ファイルがアップロードされるディレクトリを指定するのを入れてみたらどうでしょうか。
投稿者: CL (2009/02/26 19:58:29)

![すぐ解決!DTPトラブル対策ブック―最強最後のOS9(+OSX)ガイド [単行本]](http://ec2.images-amazon.com/images/I/51895BQKEPL._SL500_AA208_.jpg)









