I would like to download a file with Curl.
The problem is that the download link is not direct, for example:
http://localhost/download.php?id=13456
When I try to download the file with curl, it download the file download.php!
Here is my curl code:
###
function DownloadTorrent($a) {
$save_to = $this->torrentfolder; // Set torrent folder for download
$filename = str_replace('.torrent', '.stf', basename($a));
$fp = fopen ($this->torrentfolder.strtolower($filename), 'w+');//This is the file where we save the information
$ch = curl_init($a);//Here is the file we are downloading
curl_setopt($ch, CURLOPT_ENCODING, "gzip"); // Important
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
curl_setopt($ch, CURLOPT_URL, $fp);
curl_setopt($ch, CURLOPT_HEADER,0); // None header
curl_setopt($ch, CURLOPT_BINARYTRANSFER,1); // Binary trasfer 1
curl_exec($ch);
curl_close($ch);
fclose($fp);
}
Is there a way to download the file without knowing the path?
You may try CURLOPT_FOLLOWLOCATION
TRUE to follow any "Location: " header that the server sends as part
of the HTTP header (note this is recursive, PHP will follow as many
"Location: " headers that it is sent, unless CURLOPT_MAXREDIRS is
set).
So it will result into:
function DownloadTorrent($a) {
$save_to = $this->torrentfolder; // Set torrent folder for download
$filename = str_replace('.torrent', '.stf', basename($a));
$fp = fopen ($this->torrentfolder.strtolower($filename), 'w+');//This is the file where we save the information
$ch = curl_init($a);//Here is the file we are downloading
curl_setopt($ch, CURLOPT_ENCODING, "gzip"); // Important
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER,0); // None header
curl_setopt($ch, CURLOPT_BINARYTRANSFER,1); // Binary transfer 1
curl_exec($ch);
curl_close($ch);
fclose($fp);
}
Set the FOLLOWLOCATION option to true, e.g.:
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
Options are documented here: http://www.php.net/manual/en/function.curl-setopt.php
Oooh !
CURLOPT_FOLLOWLOCATION work perfect...
The problem is that I use CURLOPT_URL for fopen(), I simply change CURLOPT_URL whit CURLOPT_FILE
and it works very well!
thank you for your help =)
Related
I'm attempting to download a file to server with curl. I'm having a problem with the filename and saving. The filename is in persian but when i check the file in filezilla it is encoded incorrectly. It should still show the persian character.
For example the file name is:
حواشی ثبت نام دوازدهمین دوره ریاست جمهوری/ خنده دار - قسمت هفتم (7)
But when i check filezilla the filename is:
â«ÙÛÙ٠سÛÙÙاÛÛ ÙردÙا Ùرشت٠Ù.mp4
curl.php
$destination = "/home/mywebsite/public_html/wp-content/my_channels/videos/".$videoTitle.".mp4";
$file = fopen($destination, 'w');
// cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$link);
// set cURL options
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_ENCODING ,"");
// set file handler option
curl_setopt($ch, CURLOPT_FILE, $file);
// execute cURL
$result = curl_exec($ch);
$error = curl_error($ch);
// close cURL
curl_close($ch);
// close file
fclose($file);
How do i get the filename to have the persian characters?
I'm trying to download a csv that's been gz'd directly to a file:
$fp = fopen ($file.'.csv', 'w+');
$ch = curl_init($url.'/'.$file.'.csv.gz');
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
curl_exec($ch);
curl_close($ch);
fclose($fp);
What ends up happening is {$file}.csv is written to disk, however it's still encoded. If I rename the stored file {$file}.csv.gz and gunzip it the data is decoded properly.
I ended up downloading the file and creating another block of code to decode it afterwards.
$buffer_size = 262144;
$in_file_handle = gzopen($symbol.'.csv.gz', 'rb');
$out_file_handle = fopen($symbol.'.csv', 'wb');
// Keep repeating until the end of the input file
while(!gzeof($in_file_handle)) {
fwrite($out_file_handle, gzread($in_file_handle, $buffer_size));
}
// Files are done, close files
fclose($out_file_handle);
gzclose($in_file_handle);
I would however, still be very much interested in getting curl to do it all in one step.
I have one remote url which outputs the image
The url is in format like this
http://domain.com/my_file/view/<file_id>/FULL/
In the url "my_file" is a controller name, "view" is a function name and the other two are the parameters
If I hit this url in browser it shows me image
I want to take that image in my projects folder
I have tried with file_get_contents but it gives me warning with 404
How can I achieve that?
$img=file_get_contents('http://example.com/image/test.jpg');
file_put_contents('/your/project/folder/imgname.jpg',$img);
This works only if allow_url_fopen is set to 1 in your php.ini file.
If you can change this value, enable it and you're done.
Another option is CURL. Check if this module is enabled in your PHP configuration.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://example.com/image/test.jpg');
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HEADER , 0);
curl_setopt($ch, CURLOPT_VERBOSE, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$result = #curl_exec($ch);
$curl_err = curl_error($ch);
curl_close($ch);
if (empty($curl_err)) {
file_put_contents('/your/project/folder/imgname.jpg',$result);
}
If CURL is not enabled, your chance is to write a simple HTTP client like this:
$buf='';
$fp = fsockopen('example.com',80);
fputs($fp, "GET /image/test.jpg HTTP/1.1\n" );
fputs($fp, "Host: example.com\n" );
fputs($fp, "Connection: close\n\n" );
while (!feof($fp)) {
$buf .= fgets($fp,128);
}
fclose($fp);
file_put_contents('/your/project/folder/imgname.jpg',$buf);
Use Curl for this:
function curlFile($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
function readurl()
{
$url="http://domain.com/my_file/view/<file_id>/FULL/";
curlFile($url);
}
echo readurl();
If you are trying
$image = file_get_contents('http://domain.com/my_file/view/<file_id>/FULL/');
if($image) file_put_contents('some/folder/<file_id>');
and it does not work, it probably means either:
That there is access control that prevents it on the remote server. In that case, you must set the appropriate cookies. I suggest using curl to do that.
The image path is wrong; try to view source when navigating to http://domain.com/my_file/view/<file_id>/FULL/ using your browser.
The trailing / in your URL should not be there, e.g. http://domain.com/my_file/view/<file_id>/FULL?
I need to download a large file and also need to get the headers in order to get the redirect location (status code 302).
I use this:
curl_setopt($ch, CURLOPT_FILE, $file);
curl_setopt($ch, CURLOPT_HEADER, true);
Now the problem is the following:
It is writing the header data as well to the output file.
Is there a way to only write the content?
Edit:
Just to make it clear. All i want is to get the headers, but i want that only the body get's written to the file. Also please keep in mind that i can't store the body data into a variable since its a video data and therefore to big (memory_limit).
With the help of #Bishop i was able to get the working solution:
$url = 'example.com';
$file = fopen('body.txt', 'w');
$file_header = fopen('headers.txt', 'w')
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_WRITEHEADER, $file_header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
curl_setopt($ch, CURLOPT_FILE, $file);
$data = curl_exec($ch);
Now i have the header in a seperate file and can get it from there by using:
file_get_contents('headers.txt');
I want to connect to a remote file and writing the output from the remote file 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?
Actually, using fwrite is partially true.
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.
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.
Essentially, this will take each block of 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.
Cheers,
James.
Let's try sending GET request to 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:
Content-Length: 0
It means that zero bytes will be written to xxxx--all_good.txt. This is why the file stays empty.
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/.
Regarding other answers:
#JonGauthier: No, there is no need to use fwrite() after curl_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.
Seriously, three answers and every single one is invalid?
You need to explicitly write to the file using fwrite, passing it the file handle you created earlier:
if ( $httpCode == 404 ) {
...
} else {
$contents = curl_exec($curl);
fwrite($fp, $contents);
}
curl_close($curl);
fclose($fp);
In your question you have
curl_setopt($curl, CURLOPT_FILE, $fp);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
but from PHP's curl_setopt documentation notes...
It appears that setting CURLOPT_FILE before setting CURLOPT_RETURNTRANSFER doesn't work, presumably because CURLOPT_FILE depends on CURLOPT_RETURNTRANSFER being set.
So do this:
<?php
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FILE, $fp);
?>
not this:
<?php
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
?>
...stating "CURLOPT_FILE depends on CURLOPT_RETURNTRANSFER being set".
Reference: https://www.php.net/manual/en/function.curl-setopt.php#99082
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!
it seems CURLOPT_FILE depends on 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);
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.