7

リモートファイルを取得し、同時にユーザーに強制的にダウンロードしようとしています。コードを貼り付けることができません。コードが長すぎます。ただし、curl関数は機能しますが、問題は、最初にリモートファイルを取得してから、ユーザーに強制的にダウンロードするまで何も出力されないことです。

これを使用して、curlにコールバックを返すように指示します

curl_setopt($ch, CURLOPT_READFUNCTION, 'readCallback');

今私のreadCallback関数で私はこれをします:

function readCallback($curl, $stream, $maxRead){
    $read = fgets($stream, $maxRead);
    echo $read;
    return $read;
}

ただし、リモートファイルのフェッチが完了するまで待機するだけでは何も返されません。

4

3 に答える 3

9

これを試してみてください。curlを使用してファイルの合計サイズを取得し、ファイルの部分的なチャンクをダウンロードしてユーザーにプロキシします。これにより、 curlが最初にダウンロードするのを待つ必要がなくなり、avi、mp4、mp3でテストしました。とexe、それが役立つことを願っています:

<?php
$file = 'http://example.com/somefile.mp3';
download($file,2000);

/*
Set Headers
Get total size of file
Then loop through the total size incrementing a chunck size
*/
function download($file,$chunks){
    set_time_limit(0);
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-disposition: attachment; filename='.basename($file));
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Expires: 0');
    header('Pragma: public');
    $size = get_size($file);
    header('Content-Length: '.$size);

    $i = 0;
    while($i<=$size){
        //Output the chunk
        get_chunk($file,(($i==0)?$i:$i+1),((($i+$chunks)>$size)?$size:$i+$chunks));
        $i = ($i+$chunks);
    }

}

//Callback function for CURLOPT_WRITEFUNCTION, This is what prints the chunk
function chunk($ch, $str) {
    print($str);
    return strlen($str);
}

//Function to get a range of bytes from the remote file
function get_chunk($file,$start,$end){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $file);
    curl_setopt($ch, CURLOPT_RANGE, $start.'-'.$end);
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
    curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'chunk');
    $result = curl_exec($ch);
    curl_close($ch);
}

//Get total size of file
function get_size($url){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_exec($ch);
    $size = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
    return intval($size);
}
?>
于 2012-06-12T08:36:21.407 に答える
2

次のようにcurlを使用してみてください。

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_HTTPGET, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$result = curl_exec($ch);

$msg = new HttpMessage($result);
return $msg->getBody();

戻り値は、要求されたファイルの内容であり、出力することができます。したがって、コールバックは必要ありません。HTTPMessageドキュメント

于 2012-06-12T06:48:59.833 に答える
0

サーバーを強制終了せずに、大きな(8GB)リモートファイルを取得し、同時にダウンロードを強制する方法:

<?php

$url = 'http://www.example.com/bigfile.mp4';

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($url).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');

readfile($url);

readfile()関数はストリームをチャンクで読み取り、それを出力に出力するため、多くのメモリを使用しません...

于 2020-12-06T20:58:31.787 に答える