環境-----
CentOs 4.2
PHP 4.3.9
MySQL 4.1.12
質問-----
MySQLにBLOB型でバイナリデータを挿入しています。
このバイナリデータは、JPEGの画像なのですが、取り出すときに、GDを利用して縮小をさせたいと思っています。
ただ、getimagesizeやImageCreateFromJPEGの引数がデータではなく、ファイルのパスなので、どのようにして読み込ませるか困っています。
案は幾つか考えたのですが、
1.画像をhttp://example.com/toridasi.php?id=aaaと自ホストのスクリプトを参照させて読み込ませる。
2.一旦、ファイルをどこかに出力させて、処理して、unlinkする。
問題があります。
1.は、F/Wの関係で自ホストを参照できない構造になっています。Apacheも名前ベースのバーチャルなので、localhostの参照も不可です。
2,は、実現可能ですが、スマートではないのと、何らかのトラブルなどでテンポラリファイルが残りそうなのが嫌です。
なにか、解決方法はありますでしょうか?
ご教授願います。
【一応】
取り出すまでのソース
$sql = "SELECT table FROM binary WHERE id = 'sample';";
$result = mysql_query($sql);
if(mysql_num_rows($result) == 1){
$row = mysql_fetch_array($result);
$imgdat = $row["data"];
}
まだ終了されていないようですので、私見をコメントさせていただきます。
一時ファイルが残ってしまうことの不安ですが、すでにお考えかもしれませんが特定のディレクトリに一時ファイルを作成し、定期的にディレクトリのクリーニングを行えば良いのではないでしょうか。
例えば、一時ファイルの名前を元画像のキーになるID(例えばDB上のPrimary Key)+日時などにして、そのファイル名を元に一定時間経過しても残っているものは削除すれば良いと思います。
具体的には一時ファイルは tmp_00001_20060403135000.jpg のような名前にしておき、cronで1日1回ディレクトリをチェックして不要なものは削除する処理を組み込めば良いはずです。
削除のキーはファイル名ではなく、ファイルの更新日時などでも良いかもしれないですね。
また、id:zebevogueさんの回答にもありましたが、BLOB型のフィールドに画像そのものを格納するよりも、ファイルの参照のみを格納した方が少なくともパフォーマンス面では優れているようです。
通常の Web サーバセットアップを使用する場合は、画像をファイルとして格納する。言い換えると、データベース内にはファイル参照のみを格納する。この主な理由は、通常の Web サーバのほうがデータベースコンテンツと比較してファイルのキャッシュに優れているためである。このため、ファイルを使用したほうがシステムの高速化を容易に図れる。
今からそのレベルの改訂ができる状況ではなかったり、あえてBLOB型に格納している意味があるかもしれませんが、参考になると幸いです。
FIFOやソケットなどへ一旦書き出して待避し、自分でもう一度読むという手法も考えられなくはないです。1.の手法に近いです。
が、getimagesize、ImageCreateFromJPEGなど複数回呼び出すのですよね?
FIFOやソケットだと、一回読み出すとデータが消えてしまいますので、その都度書き出し直さなければならず、結局一時ファイルを使う以上にやぼったい処理になってしまいます。
ということで、一時ファイルを使うのが、処理的には一番スマートだと思います。
一時ファイルのファイル名は、phpの処理が複数同時に実行される可能性がないのなら、パス名を固定にしてしまえば、少なくともトラブルでファイルが残っても1個以上増えることはありません。
なるほど、そうですよね。
ありがとうございます。
オリジナルサイズの画像が不要なら縮小画像のみ格納してはどうでしょう?
または、単純に両方の画像をDBに格納する方法ではどうでしょう?画像取得時のパフォーマンスは上がると思います。
もしくは、DBに格納するのはファイルのパスとして、ファイルシステム上に実ファイルを置くのもありだと思います。実ファイルにアクセスする際にクッションとしてIDやセッション等を使用すれば実際のパスが利用者に分からなくさせる事(直リンクの防止)もできます。
最初の格納時には、一応縮小させて入れているのですが、DBから呼び出すときに、色んなサイズで呼び出されるのです。
書いていませんでしたね。
ありがとうございます。
まだ終了されていないようですので、私見をコメントさせていただきます。
一時ファイルが残ってしまうことの不安ですが、すでにお考えかもしれませんが特定のディレクトリに一時ファイルを作成し、定期的にディレクトリのクリーニングを行えば良いのではないでしょうか。
例えば、一時ファイルの名前を元画像のキーになるID(例えばDB上のPrimary Key)+日時などにして、そのファイル名を元に一定時間経過しても残っているものは削除すれば良いと思います。
具体的には一時ファイルは tmp_00001_20060403135000.jpg のような名前にしておき、cronで1日1回ディレクトリをチェックして不要なものは削除する処理を組み込めば良いはずです。
削除のキーはファイル名ではなく、ファイルの更新日時などでも良いかもしれないですね。
また、id:zebevogueさんの回答にもありましたが、BLOB型のフィールドに画像そのものを格納するよりも、ファイルの参照のみを格納した方が少なくともパフォーマンス面では優れているようです。
通常の Web サーバセットアップを使用する場合は、画像をファイルとして格納する。言い換えると、データベース内にはファイル参照のみを格納する。この主な理由は、通常の Web サーバのほうがデータベースコンテンツと比較してファイルのキャッシュに優れているためである。このため、ファイルを使用したほうがシステムの高速化を容易に図れる。
今からそのレベルの改訂ができる状況ではなかったり、あえてBLOB型に格納している意味があるかもしれませんが、参考になると幸いです。
ありがとうございます。
参考にします。
tempnam()を使用し、システムのtemporaryに放り込み、最後にunlink()することで、取り敢えずの解決としました。
もちろん、途中で止まったときは、ファイルが残ってしまう可能性がありますが、取り敢えずと言うことで。
本当は、tmpfile()の様なもので、ファイル名とのやりとりも出来れば最高だったんですが・・・
ありがとうございました。
ありがとうございます。
参考にします。
tempnam()を使用し、システムのtemporaryに放り込み、最後にunlink()することで、取り敢えずの解決としました。
もちろん、途中で止まったときは、ファイルが残ってしまう可能性がありますが、取り敢えずと言うことで。
本当は、tmpfile()の様なもので、ファイル名とのやりとりも出来れば最高だったんですが・・・
ありがとうございました。