PHP

【PHP】大きいリモートファイルをfreadすると途中で切れる【理由と解決法】

投稿日:2018年11月15日 更新日:

PHPでリモートファイル(httpやsshで読み込むファイル)をfreadする際、容量の大きいファイルを読み込むと、読み込みが途中で切れる事があります。

エラーなど発生せず、freadの結果が読み込みファイルの途中で途切れてしまいます。
ちょっとやっかいですよね。

これはfreadの仕様でして、リモートファイルを読み込む場合は別の方法をで実装した方が良いです。

読み込みが切れる理由と、正しい実装方法をご紹介します。

スポンサーリンク

【理由】リモートファイルをfreadすると途中でファイル読み込みが切れる

リモートファイルをfreadすると、途中でファイル読み込みが切れる事があります。

恐ろしいのは、そこそこのファイルサイズじゃないと切れないので大きいサイズのファイルでテストしていないと気づかないんですよね。
テストをスルーして本番で不具合発覚なんてケースになりえるので要注意です。

なぜファイルの読み込みが途中で切れちゃうかというと…

警告
通常のローカルファイル以外のもの、例えば リモートファイル や popen()、fsockopen() が返す ストリームを読み込んでいる場合には、 パケットが有効になった後に読み込みはストップします。 つまり以下の例のように分割されたデータを結合すべきであるということです。

PHPリファレンスにちゃんと書いてありました。

ようはリモートファイルをfreadする場合は、パケットの単位で読み込みが途切れてしまうのです。

ちなみに、リファレンスではhttpでファイルを開いたケースが紹介されいますが、僕はssh2で読み込んだファイルで発生しました。

リモートファイルの読み込み全般で発生すると思われます。

【対策】freadではなくstream_get_contentsを使おう

正しい実装方法もリファレンスに書いてあります。

解決方法を引用します。

PHP5以降

<?php
// PHP 5 以降での例
$handle = fopen("http://www.example.com/", "rb");
$contents = stream_get_contents($handle);
fclose($handle);
?>

PHP5未満

<?php
$handle = fopen("http://www.example.com/", "rb");
if (FALSE === $handle) {
    exit("Failed to open stream to URL");
}

$contents = '';

while (!feof($handle)) {
    $contents .= fread($handle, 8192);
}
fclose($handle);
?>

参考:PHPリファレンス

PHP5以降であれば、freadstream_get_contentsに変えればOKです。

PHP5未満の場合は、読み込み完了をチェックしながらループで繰り返しfreadする必要があります。

まとめ:リモートファイルの読み込みにfreadを使う場合は要注意

なかなかテストで気づけない不具合になりうるので、覚えておきましょう。

実際僕は、これで不具合をだしてしまいましたので…

最後までお読み頂きありがとうございました!

スポンサーリンク


-PHP

執筆者:

関連記事

PhpStormに乗り換えて良かった!オススメの5つの機能

EclipseからPhpStormに乗り換えて2年目に突入し、迷わずPhpStormのライセンスを更新しました。 PhpStormにはかな〜り満足しています。 開発効率はだいぶ上がったんじゃないでしょ …

【PHP】デフォルトの設定だと大量のPOSTパラメーターは途中で切れるので注意!!

PHPで大量のデータをPOSTすと、POSTしたデータが途中で切れるという問題が発生。 原因はなんて事はなく、php.iniの設定の問題でした。 対応方法を解説します。 スポンサーリンク 目次max_ …

EclipseからPhpStormへ乗り換える時に行った事

こんにちは! DENです! 僕はもともとJavaエンジニアだったので、PHPの開発ももっぱらEclipseです。 もう10年近くEclipseを使っています。 使い慣れたIDEで不満もなく使っていまし …

【PHP】バックトーレス(呼び出し階層)をデバッグ出力する方法

PHPでバックトレースを出力する方法について解説します。 バックトレースというのは、呼び出し階層のようなものです。 エラーが発生した時に、何行目でエラーが発生してどのようなルートでメソッドが呼び出され …

RewriteEngine onで403エラーの解決方法

ローカル環境でRewriteEngine onにしたら、403エラーが発生。 その解決方法の解説です。 スポンサーリンク 目次環境についてFollowSymLinksを有効にする事で解決まとめ 環境に …

プロフィール

このサイトを運営しているDENです。
アングラーのフリープログラマー。 主にプログラミングと釣の話を発信しています。
プログラミングで自由になり思う存分に釣りをしまくる生活実践中。
詳しいプロフィールはこちら