4

PHPスクリプトを介してURLからユーザーにダウンロードを提供しています。使用するreadfile()と、接続でサポートできる最大ダウンロード速度(約2.5MB /秒)が得られますが、fopen, fread, fcloseルートを使用すると、ダウンロード速度が非常に遅くなります(約1〜2KB /秒)。

これが私のコードです:

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $filename);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . $filesize);
ob_clean();
flush();

$file = fopen($url, 'rb');

while(!feof($file)) {
    echo fread($file, 2014);
}

読み取りファイルのコードは単純readfile($link);です。

この機能を使用できないreadfile()理由は2つあります。1つは、ユーザーのダウンロード速度を制限したい(これはfread、大量のデータを読み取るだけで実行できます)。また、ユーザーがダウンロードしている量を追跡したい(Iでこれを行うことができますreadfile()が、部分的なダウンロードはカウントされません)。

なぜこれが起こっているのか、またはどうすれば修正できるのか誰かが知っていますか?私の知る限り、これreadfile()は単なるラッパーfopen, fread and fcloseなので、何がうまくいかないのかわかりません。

編集:このためにcURLを使用することになりました。

$curl = curl_init();
$options = array(
    CURLOPT_URL => $rdLink,
    CURLOPT_FAILONERROR => true,
    CURLOPT_BINARYTRANSFER => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_WRITEFUNCTION => 'readResponse'
);
curl_setopt_array($curl, $options);

if(!curl_exec($curl)) {
    header('Location: http://whatever.com');
    exit;
}
curl_close($curl);

function readResponse($ch, $data) {
    $length = mb_strlen($data, '8bit');

    echo $data;

    return $length;
}
4

3 に答える 3

3

stream_context_create()およびstream_get_contents( )を使用します

$context = stream_context_create();
$file = fopen($url, 'rb', FALSE, $context);
while(!feof($file))
{
    //usleep(1000000);
    echo stream_get_contents($file, 2014);
}

また、ファイルの読み取り長を長くし、usleep()を挿入して実行を遅くすることもできます。とにかく、最新バージョンのPHPには、freadよりもストリーム関数が推奨されているようです。少なくとも本番環境では、エラーを抑制するために、fread()またはstream_get_contents()の前に@を追加することもできます。それがなければ、そして少しの事故で、あなたは壊れたファイルを持っています。

于 2013-02-03T08:34:11.920 に答える
0

PHPまたはApacheのどこかでバッファリング(またはおそらくレート制限)している可能性があります。変更してみてください:

while(!feof($file)) {
   echo fread($file, 2014);
}

に:

while(!feof($file)) {
   $s=fread($file, 2014);
   if($s===false)break;  //Crude
   echo $s;
   @ob_flush();@flush();
}

@プレフィックスは、空のバッファーについて文句を言う可能性があるためです。)

mr.freshwaterが言ったように、あなたはあなたのfread呼び出しでエラーチェックをするべきです、それで私は上に基本的な何かを追加しました。

于 2013-02-03T08:51:39.070 に答える
0

その理由は2014年です。OSは4096バイトのデータ部分を他の部分よりも非常に高速に取得します。ただし、2014を作成すると、OSはファイルから1バイトずつデータを読み取って計算しようとします。だから時間がかかるのです。2014を4096に変更します

于 2017-07-20T12:59:20.597 に答える