问题描述
我需要一种方法,可以从外部URL加载大文件并将其上传到其他目标,而无需实际将其临时保存在本地。上载由接受资源或StreamInterface作为源的外部包处理。我浏览了一些耗时的文档,但找不到合适的解决方案。
到目前为止,我一直坚持这样的想法:
# Download
$client = new GuzzleHttp\Client(['base_uri' => 'https://host.com']);
$resource = fopen('tmp_file','w');
$stream = GuzzleHttp\Psr7\stream_for($resource);
$client->request('GET','/test.zip',[
'sink' => $stream,]);
# Upload
$uploadHandler->upload($stream);
不幸的是,那根本行不通。开始上载之前,文件已被完整下载。目的地也没有收到可用的文件-我无法确切看到它收到的内容,但是它为空或损坏。
因此,总而言之,如果文件正在下载时被“传递”(上传)(上传),则是理想的选择。如果本地缓冲区文件很小,也可以。
这完全可行吗?
解决方法
您是否尝试过使用curl流式传输文件。我在此处编写此代码,因此可能需要进行其他测试,但具体操作如下:
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL,"http://remote.server/file_handler.php");
curl_setopt($curl,CURLOPT_USERPWD,"user:pass");
// to return the result as a string and not output it directly
curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl,CURLOPT_PUT,true);
// This is the remote file and if it is a stream you will need it's content length
// meta_data will provide you with this
$file = 'http://host.com/test.zip';
$fp = fopen($file,"r");
$meta = stream_get_meta_data($fp);
curl_setopt($curl,CURLOPT_INFILESIZE,$meta['unread_bytes']);
curl_setopt($curl,CURLOPT_INFILE,$fp);
curl_exec($curl);
curl_close($curl);
fclose($fp);
作为服务器密集型操作,您还可以查看php提供的ftp服务:https://www.php.net/manual/en/ref.ftp.php,更确切地说是 ftp_append 或 ftp_put
但是我的建议是先尝试使用上述脚本。
PS
$ file 变量表示您所说的 http://host.com/test.zip 远程文件,而远程服务器是 CURLOPT_URL 中的字符串。从理论上讲,至少您是将正在读取的流从一个远程服务器传递到另一台远程服务器。
PS
这样,您可以将头文件添加到远程文件的fopen中。
$options = [
'http' => [
'method'=>"GET",'header'=>"Accept-language: EN\r\n ANOTHER-HEADER: test=test"
]
];
$defineContext = stream_context_create($options);
$fp = fopen('http://host.com/test.zip','r',false,$defineContext);
您可以参考这个以获取更多详细信息:https://www.php.net/stream-context-create