Authentication




Cancel OK
B!コメントする  2015-02-05 16:27:00 by admin

PHPで大きなものをダウンロードさせる

特に何もなければ2MByteの壁がある。
PHPなんかの設定でもあり、メモリーを無駄に使いすぎないようにするための施策でもある。
でも最近は2MByteではとてもじゃないが足りないことが多い。
開発ならまだしもスマホから投稿される画像ですらこの制限をオーバーする。

解決策としてはこの設定をphp.iniや.htaccessで変更することで解消できるが、これには場合によっては限度がある。
あるサーバーで20MByte程度のデータをやりとりすることなり、余裕をもって設定値を24Mにしたらエラーになってダウンロードが出来ない。
仮に設定出来たとしても実際にデータを送れるかどうかはわからないし、複数人が同時にしていたらメモリーの消費も莫大になるのでメモリーを増やすだけの対応はおすすめ出来ない。
仮にこのやり方で問題が起きるのはこういったダウンロード

// --------------------------
// ファイル取得
// --------------------------

$package = "hogehoge.jpg";
$fp = fopen($package, "r");
clearstatcache();
$content = fread($fp, filesize($package));
fclose($fp);

// --------------------------
// ファイル送信
// --------------------------

// MIME送出
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=$package");
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($package));

echo $content;

対象となるファイルを読み込み、その内容をまとめて送信する。
これを回避するには細切れにして送ってやることで解決できる。

// --------------------------
// ファイル取得
// --------------------------
$package = "hogehoge.jpg";
$fp = fopen($package, "r");
clearstatcache();
$content = fread($fp, filesize($package));
fclose($fp);

// --------------------------
// ファイル送信
// --------------------------

// MIME送出
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=$package");
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($package));

$handle = fopen($package, 'rb');  
while (!feof($handle))  
{  
    echo fread($handle, 4096);  
    ob_flush();  
    flush();  
}  
fclose($handle);  

これは4096byte毎に区切ってデータを送ることでメモリー消費を抑えていると共に、エラーに対応している。
実際には使用想定数やサイズからリミットは変更しておくべきなので設定の変更も見ておく必要はある。

これからやりとりするファイルの大きさはどんどん大きくなってくると思う。 昔からあるやり方ではあるし、最近ではフレームワークなんかで自動であれこれしてくれることも多いけど知っておいて損はないと思います。


PHP プログラム TIPS  

  • コメント
  • コメントはまだありません