Php Curl_multi在文件下载时过早退出

Php Curl_multi在文件下载时过早退出,php,multithreading,curl,proxy,Php,Multithreading,Curl,Proxy,当使用单个线程运行文件下载到文件指针时,它可以正常工作。当使用多线程时,它不会下载完整的文件(在中间的某个地方停止) 单螺纹(工程) 多线程(下载不完整) 我在输出之前需要这些头的主要原因是捕获后端的错误。(单线程方法将产生200OK头,即使服务器响应404或500)。这将有效地破坏文件中的数据 如何确保将完整文件发送到php://output 在PHP停止向浏览器发送数据并仍然使用curl_multi(这样我就可以代理大文件,包括标题)之前,我在下面找到了答案: 使用CURLOPT_FILE和

当使用单个线程运行文件下载到文件指针时,它可以正常工作。当使用多线程时,它不会下载完整的文件(在中间的某个地方停止)

单螺纹(工程)

多线程(下载不完整)

我在输出之前需要这些头的主要原因是捕获后端的错误。(单线程方法将产生200OK头,即使服务器响应404或500)。这将有效地破坏文件中的数据

如何确保将完整文件发送到php://output 在PHP停止向浏览器发送数据并仍然使用curl_multi(这样我就可以代理大文件,包括标题)之前,我在下面找到了答案:

使用CURLOPT_FILE和curl_multi时似乎出现了一些意外行为。解决方法是显式调用
fclose($bodyStream)

$fp = fopen('php://output', 'w');
$ch = curl_init(str_replace(" ", "%20", $url)); //Here is the file we are downloading, replace spaces with %20
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$return = curl_exec($ch); // get curl response
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
fclose($fp);
$bodyStream = fopen('php://output', 'w');
$headerStream = fopen('php://temp', 'rw');

$ch = curl_init(str_replace(" ", "%20", $url)); //Here is the file we are downloading, replace spaces with %20
curl_setopt($ch, CURLOPT_WRITEHEADER, $headerStream);
curl_setopt($ch, CURLOPT_FILE, $bodyStream);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

$mh = curl_multi_init();
curl_multi_add_handle($mh, $ch);
$headerProcessed = false;
ob_start(); // Buffer body output until headers are ready
do {
    $mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while ($active && $mrc == CURLM_OK) {
    do {
        $mrc = curl_multi_exec($mh, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);

    // Process headers
    if (!$headerProcessed) {
        $currentPos = ftell($headerStream);
        rewind($headerStream);
        $header = stream_get_contents($headerStream);
        fseek($headerStream, $currentPos); // Is this really needed?
        if (strpos($header, "\r\n\r\n") !== false) {
            // Copy headers such as Content-Length etc.
            $this->generateProxyHeader($header);

            // Headers set. Now send output to browser
            $headerProcessed = true;
            ob_end_flush();
        }
    }
}
curl_multi_remove_handle($mh, $ch);
curl_multi_close($mh);
exit; // Download complete, stop processing