PHP cURL 实时代理(流文件)

Posted

技术标签:

【中文标题】PHP cURL 实时代理(流文件)【英文标题】:PHP cURL Realtime proxy (stream file) 【发布时间】:2016-11-19 22:01:33 【问题描述】:

目前我有如下脚本:

<?php
$filename = "http://someurl.com/file.ext";
header('Content-Type: application/octet-stream');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$filename);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 500);
$data=curl_exec($ch);
curl_close($ch);
echo $data;
?>

问题是服务器在下载整个文件后才发送响应。我想让它像“流”一样工作,在下载文件时发送数据块作为响应。

用 PHP 和 cURL 可以实现吗?

【问题讨论】:

This 可能就是您要找的。​​span> 我以前从未使用过composer,我在共享主机中,但我会搜索更多。 【参考方案1】:

这是可能的。您可以使用 curl 选项 CURLOPT_WRITEFUNCTION 指定一个回调,您将在其中接收数据块,以便您可以在 curl 下载文件时直接将它们发送到客户端。

<?php

$filename = "http://someurl.com/file.ext";
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$filename);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 500);
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($curl, $data) 
    echo $data;
    return strlen($data);
);
curl_exec($ch);
curl_close($ch);

【讨论】:

使用 5 mb 文件对其进行了测试。我相信它不会只是逐渐发送块,而是发送已经从开始多次传输的数据,或者它在某种程度上已损坏。这需要特定的php版本? write 函数不应该两次接收相同的数据。最低 PHP 版本为 5.3,以允许将匿名函数提供给 CURLOPT_WRITEFUNCTION。否则没有要求。我再次尝试了从 5 MB 到 480 MB 的各种文件,它几乎立即开始在我的计算机上下载,文件校验和匹配并正常打开。 我终于找到了问题,是由cloudflare引起的...代码按预期工作。谢谢。 工作正常..!谢谢@drew010 @SuperNova 不保证发送长度。如果他们发送内容长度标头,则很容易使用CURLOPT_HEADERFUNCTION 获取并在发送任何数据之前发送它。您也可以从this 我的其他答案中借用一些逻辑,该答案显示了如何获取远程资源的内容长度。【参考方案2】:

Curl 默认会直接输出响应,除非你指定CURLOPT_RETURNTRANSFER

您的代码只需删除CURLOPT_RETURNTRANSFER 和最后一个echo 即可工作:

<?php
$filename = "http://someurl.com/file.ext";
header('Content-Type: application/octet-stream');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$filename);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 500);
$data=curl_exec($ch);
curl_close($ch);
?>

【讨论】:

CURLOPT_RETURNTRANSFER 是阻止该默认行为的几个选项之一。其他包括:CURLOPT_NOBODYCURLOPT_FILECURLOPT_WRITEFUNCTION

以上是关于PHP cURL 实时代理(流文件)的主要内容,如果未能解决你的问题,请参考以下文章

PHP 获取网络接口文件流

PHP——curl使用代理

PHP 获取网络接口文件流

带有 curl 短信的 php 在实时服务器上发送

将PHP配置为使用代理服务器来实现curl的功能

PHP 使用 fsockopen/cURL 设置浏览器代理