PHP cURL,写入文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7967531/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP cURL, writing to file
提问by Ryan
I want to try connecting to a remote file and writing the output from there to a local file, this is my function:
我想尝试连接到远程文件并将输出从那里写入本地文件,这是我的功能:
function get_remote_file_to_cache()
{
$the_site="http://facebook.com";
$curl = curl_init();
$fp = fopen("cache/temp_file.txt", "w");
curl_setopt ($curl, CURLOPT_URL, $the_site);
curl_setopt($curl, CURLOPT_FILE, $fp);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_exec ($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
touch('cache/404_err.txt');
}else
{
touch('cache/'.rand(0, 99999).'--all_good.txt');
}
curl_close ($curl);
}
It creates the two files in the "cache" directory, but the problem is it does not write the data into the "temp_file.txt", why is that?
它在“缓存”目录中创建了两个文件,但问题是它没有将数据写入“temp_file.txt”,这是为什么呢?
Thanks!
R
谢谢!
电阻
采纳答案by Jon Gauthier
回答by doublehelix
Actually, using fwrite is partiallytrue. In order to avoid memory overflow problems with large files (Exceeded maximum memory limit of PHP), you'll need to setup a callback function to write to the file.
实际上,使用 fwrite 是部分正确的。为了避免大文件的内存溢出问题(超出 PHP 的最大内存限制),您需要设置一个回调函数来写入文件。
NOTE:I would recommend creating a class specifically to handle file downloads and file handles etc. rather than EVER using a global variable, but for the purposes of this example, the following shows how to get things up and running.
注意:我建议创建一个专门用于处理文件下载和文件句柄等的类,而不是永远使用全局变量,但就本示例而言,以下内容显示了如何启动和运行。
so, do the following:
因此,请执行以下操作:
# setup a global file pointer
$GlobalFileHandle = null;
function saveRemoteFile($url, $filename) {
global $GlobalFileHandle;
set_time_limit(0);
# Open the file for writing...
$GlobalFileHandle = fopen($filename, 'w+');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FILE, $GlobalFileHandle);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_USERAGENT, "MY+USER+AGENT"); //Make this valid if possible
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); # optional
curl_setopt($ch, CURLOPT_TIMEOUT, -1); # optional: -1 = unlimited, 3600 = 1 hour
curl_setopt($ch, CURLOPT_VERBOSE, false); # Set to true to see all the innards
# Only if you need to bypass SSL certificate validation
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
# Assign a callback function to the CURL Write-Function
curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'curlWriteFile');
# Exceute the download - note we DO NOT put the result into a variable!
curl_exec($ch);
# Close CURL
curl_close($ch);
# Close the file pointer
fclose($GlobalFileHandle);
}
function curlWriteFile($cp, $data) {
global $GlobalFileHandle;
$len = fwrite($GlobalFileHandle, $data);
return $len;
}
You can also create a progress callback to show how much / how fast you're downloading, however that's another example as it can be complicated when outputting to the CLI.
您还可以创建一个进度回调来显示您下载的数量/速度,但这是另一个示例,因为它在输出到 CLI 时可能会很复杂。
Essentially, this will take each blockof data downloaded, and dump it to the file immediately, rather than downloading the ENTIRE file into memory first.
本质上,这将获取下载的每个数据块,并将其立即转储到文件中,而不是先将整个文件下载到内存中。
Much safer way of doing it! Of course, you must make sure the URL is correct (convert spaces to %20 etc.) and that the local file is writeable.
更安全的做法!当然,您必须确保 URL 正确(将空格转换为 %20 等)并且本地文件是可写的。
Cheers, James.
干杯,詹姆斯。
回答by stil
Let's try sending GET request to http://facebook.com
:
让我们尝试将 GET 请求发送到http://facebook.com
:
$ curl -v http://facebook.com * Rebuilt URL to: http://facebook.com/ * Hostname was NOT found in DNS cache * Trying 69.171.230.5... * Connected to facebook.com (69.171.230.5) port 80 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.35.0 > Host: facebook.com > Accept: */* > < HTTP/1.1 302 Found < Location: https://facebook.com/ < Vary: Accept-Encoding < Content-Type: text/html < Date: Thu, 03 Sep 2015 16:26:34 GMT < Connection: keep-alive < Content-Length: 0 < * Connection #0 to host facebook.com left intact
What happened? It appears that Facebook redirected us from http://facebook.com
to secure https://facebook.com/
. Note what is response body length:
发生了什么?看来 Facebook 将我们从 重定向http://facebook.com
到了 secure https://facebook.com/
。注意什么是响应体长度:
Content-Length: 0
It means that zero bytes will be written to xxxx--all_good.txt
. This is why the file stays empty.
这意味着零字节将被写入xxxx--all_good.txt
. 这就是文件保持为空的原因。
Your solution is absolutelly correct:
您的解决方案是完全正确的:
$fp = fopen('file.txt', 'w');
curl_setopt($handle, CURLOPT_FILE, $fp);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
All you need to do is change URL to https://facebook.com/
.
您需要做的就是将 URL 更改为https://facebook.com/
.
Regarding other answers:
关于其他答案:
- @JonGauthier: No, there is no need to use
fwrite()
aftercurl_exec()
- @doublehelix: No, you don't need
CURLOPT_WRITEFUNCTION
for such a simple operation which is copying contents to file. - @ScottSaunders:
touch()
creates empty file if it doesn't exists. I think it was intention of OP.
- @JonGauthier:不,
fwrite()
后不需要使用curl_exec()
- @doublehelix:不,您不需要
CURLOPT_WRITEFUNCTION
将内容复制到文件的这种简单操作。 - @ScottSaunders:
touch()
如果文件不存在,则创建空文件。我认为这是OP的意图。
Seriously, three answers and every single one is invalid?
说真的,三个答案,每一个都无效?
回答by Scott Saunders
The touch()
function doesn't do anything to the contents of the file. It just updates the modification time. Look at the file_put_contents() function
.
该touch()
函数不会对文件的内容做任何事情。它只是更新修改时间。看看file_put_contents() function
.
回答by gezdy
To avoid memory leak problems:
为避免内存泄漏问题:
I was confronted with this problem as well. It's really stupid to say but the solution is to set CURLOPT_RETURNTRANSFER before CURLOPT_FILE!
我也遇到了这个问题。说起来真的很愚蠢,但解决方案是在 CURLOPT_FILE 之前设置 CURLOPT_RETURNTRANSFER!
it seems CURLOPT_FILE depends on CURLOPT_RETURNTRANSFER.
似乎 CURLOPT_FILE 取决于 CURLOPT_RETURNTRANSFER。
$curl = curl_init();
$fp = fopen("cache/temp_file.txt", "w+");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FILE, $fp);
curl_setopt($curl, CURLOPT_URL, $url);
curl_exec ($curl);
curl_close($curl);
fclose($fp);