PHP + CURL How to get file name - php

I'm trying to download users profile picture from facebook in PHP using this function
public static function downloadFile($url, $options = array())
{
if (!is_array($options))
$options = array();
$options = array_merge(array(
'connectionTimeout' => 5, // seconds
'timeout' => 10, // seconds
'sslVerifyPeer' => false,
'followLocation' => true, // if true, limit recursive redirection by
'maxRedirs' => 2, // setting value for "maxRedirs"
), $options);
// create a temporary file (we are assuming that we can write to the system's temporary directory)
$tempFileName = tempnam(sys_get_temp_dir(), '');
$fh = fopen($tempFileName, 'w');
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_FILE, $fh);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $options['connectionTimeout']);
curl_setopt($curl, CURLOPT_TIMEOUT, $options['timeout']);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $options['sslVerifyPeer']);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, $options['followLocation']);
curl_setopt($curl, CURLOPT_MAXREDIRS, $options['maxRedirs']);
curl_exec($curl);
curl_close($curl);
fclose($fh);
return $tempFileName;
}
The problem is it saves the file in the /tmp directory with a random name and without the extension. How can I get the original name of the file (I'm more interested in the original extension)
The important things here are:
The url actually redirects to image so i cant get it from original url
the final url does not have the file name in headers

If the URL redirects to an image, you should still be able to get the filename from the headers. Using a browser with dev tools like Chrome, you can look at the headers going back and forth from your original request to the resultant file, and the filename has to be in there somewhere. With that said, I was under the impression that Facebook rewrites all images to their own filenames for privacy reasons.
You can recreate the extension based on the content type of the response.
After running curl_exec(), try:
$content_type = curl_getinfo($curl,CURLINFO_CONTENT_TYPE);
This will return something like "image/jpg" for a JPEG, for example. You can then rename your temp file to have the proper extension.
If you can use PHP 5.3, a possibly cleaner way to do this would just be to call finfo_file() on the file after it is downloaded, which should read the MIME type, allowing you to select a proper extension without relying on header data. finfo_file() is also available in the fileinfo PECL extension.

If you're just looking for the image type (jpg/png/gif) and you have the GD extension installed you can use getimagesize, it returns the image type along with other details. It's more accurate than looking at the file extension.
image_type_to_mime_type might also help once you've used getimagesize.

Related

How Do I Download Facebook Images Using cURL?

I have a PHP script that works just fine downloading most remote images to my file system, but when I try to download a Facebook or Instagram image I get an error that says "failed to open stream: No error in" followed by the line of my fopen function and two additional errors "fwrite() expects parameter 1 to be resource, bool given in" which is obviously due to the Facebook image not downloading.
My code is as follows:
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_BINARYTRANSFER,1);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_REFERER, "https://www.facebook.com/");
curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)');
$page = curl_exec($curl);
if(curl_errno($curl)):
echo 'Erro: ' . curl_error($curl);
exit;
endif;
curl_close($curl);
// Use basename() function to return the base name of file
$file_name = basename($url);
if(file_exists($file_name)){
unlink($file_name);
}
$fp = fopen($file_name,'x');
fwrite($fp, $page);
fclose($fp);```
There also seems to be an error when I try to add the first line of code to this post which is:
```$url = 'https://scontent-sea1-1.xx.fbcdn.net/v/t1.0-0/p180x540/119041795_176402070632464_6192328410277888324_o.jpg?_nc_cat=111&ccb=2&_nc_sid=825194&_nc_ohc=O7khk9mGFO4AX86nd5X&_nc_ht=scontent-sea1-1.xx&tp=6&oh=ff35f5eaf960fa7bd30ab1d549f0d817&oe=6045A0D1';```
Screenshot APIs are the workaround for this. There are many, but to spare the one I am using from any scrutiny for how it is being used by now I will not name the specific program. Most are basically the same, but you should choose one that allows you to install it on your own system rather than being dependent on simply getting a screenshot from a URL of theirs. That way you can encode the Facebook/Instagram image URL that you want to take a screenshot of, send the encoded URL to the API, and save the result on your file system.
The ability to encode the URL is key because of all the query strings in Facebook/Instagram image URLs.

Remove file path from CURL file upload request

I am using CURL to POST upload files on a web-service. Server returns a XML with file name with which it puts file in a storage DB for further processing. Simplified code below:
$post['uploadfile'] = new CurlFile('src/files/file.png', 'image/png');
$ch = curl_init($target_url);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$result = curl_exec($ch);
Server side code is unavailable for me, and the problem is that server returns me a path for the uploaded file like this:
src_files_file.png
I guess i have missed a field in request, that holds clear name for file. How could it be resolved to
file.png
I not sure that I fully understand your question, but I think you search third parameter in CurlFile constructor:
$post['uploadfile'] = new CurlFile('src/files/file.png', 'image/png', 'file.png');

Save mp3 file from a download link on your hosting space using PHP

I am fetching data from API of a service provider (Say- http://serviceprovider.com).
From several parameter one is MP3 download Link (example- http://serviceprovider.com/storage/read?uid=475b68f2-a31b-40f8-8dfc-5af791a4d5fa_1_r.mp3&ip=255.255.255.255&dir=recording)
When I put this download link on my browser it saves it to my local PC.
Now My Problem -
I want to save this MP3 file in one of folder on my hosting space, from where I can further use it for playing using JPlayer Audio.
I have tried file_get_contents(), but nothing happened.
Thanks in advance.
Edit:
After reading Ali Answer I tried the following code, But still not working fully.
// Open a file, to which contents should be written to.
$fp = fopen("downloadk.mp3", "w");
$url = 'http://serviceprovider.com/storage/read?uid=475b68f2-a31b-40f8-8dfc-5af791a4d5fa_1_r.mp3&ip=255.255.255.255&dir=recording';
$handle = curl_init($url);
// Tell cURL to write contents to the file.
curl_setopt($handle, CURLOPT_FILE, $fp);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_HEADER, false);
// Do the request.
$data = curl_exec($handle);
// Clean up.
curl_close($handle);
fwrite($fp, $data);
fclose($fp);
This created the file download.mp3 file on my server but with 0 bytes, i.e. empty.
The url used here is a download link example not a mp3 file that can be played with modern browser directly.
Function file_get_contents is used for reading local files. What you have is an URL and in order to fetch the contents, you need to do a HTTP request in your script. PHP comes with the curl extension, which provides you with a stable library of functions for doing HTTP requests:
http://php.net/manual/en/book.curl.php
Using curl to download your file could be done like this:
// Open a file, to which contents should be written to.
$downloadFile = fopen("download.mp3", "w");
$url = "http://serviceprovider.com/storage/read?uid=475b68f2-a31b-40f8-8dfc-5af791a4d5fa_1_r.mp3&ip=255.255.255.255&dir=recording";
$handle = curl_init($url);
// Tell cURL to write contents to the file.
curl_setopt($handle, CURLOPT_FILE, $downloadFile);
// Follow redirects.
curl_setopt($handle, CURLOPT_FOLLOWLOCATION, true);
// Do the request.
curl_exec($handle);
// Clean up.
curl_close($handle);
fclose($downloadFile);
You should probably add some error checking.

Saving remote image with php

The following code retrieves an image and saves it to a local folder. A jpg file is indeed saved to local disk, with around 40KB filesize (seems correct). When I put the local path in an img tag, the file does not display.
Firebug > Inspect Element shows a size of 0 X 0 and I'm unable to view the image when saved to my desktop.
file_put_contents, file_get_contents and getimagesize don't return FAILs. $url IS a valid image. The problem is just saving it locally, the file seems to be corrupt - how come?
$url = $image->request_url; //the image generated on the remote server
//print_r(getimagesize($url)); die;
$img = 'thumbalizr/cache/screenshot_' . $row['id'] . '.jpg'; //path to our local cache folder + unique filename
if( !$captured_file = file_get_contents($url) ) die('file could not be retrieved');
elseif( !file_put_contents($img, $captured_file, FILE_APPEND) ) die('file could not be written to local disk'); //write the image to our local cache
"Are you sure the path is correct? Have you tried an absolute path?" YES
"Have you checked that the image is downloaded correctly, perhaps with another utility (e.g. ftp, diff)?" I can download the img via ftp but it does not open on my local computer either.
"What do you get if you call the URL directly in the browser?" FF just prints out the URL instead of showing the image
"Why are you using FILE_APPEND? if the target already exists, this writes to the end, which will naturally give you a corrupt image" I removed FILE_APPEND, no difference
"source and final extension are the same?" Yes I tried with jpg, jpeg and png - no difference
"First of all, example code is wrong. Can't use $capture_file in file_put_content because that variable is not defied becouso of if else if block logic." - WRONG, that code does run!
"Can you look into the image file" - no! Although the file has a realistic file size and I can download it, it's impossible to open it.
First off check the files you're been downloading in a text editor to see if you're getting HTML error pages instead of binary image data.
Second, I would use curl for this as it provides better success/error information. Here's your example modified to use it.
//path to our local cache folder + unique filename
$img_path = 'thumbalizr/cache/screenshot_' . $row['id'] . '.jpg';
$c = curl_init();
curl_setopt($c, CURLOPT_URL, $image->request_url);
curl_setopt($c, CURLOPT_HEADER, 0);
curl_setopt($c, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($c, CURLOPT_AUTOREFERER, true);
curl_setopt($c, CURLOPT_BINARYTRANSFER, true);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($c, CURLOPT_FORBID_REUSE, true);
// curl can automatically write the file out for you
curl_setopt($c, CURLOPT_FILE, $img_path);
// You can get more elaborate success/error info from
// curl_getinfo() http://www.php.net/manual/en/function.curl-getinfo.php
if (!curl_exec($c)) {
die('file could not be retrieved');
}

Post Uploaded file to another PHP page?

Here is my problem. I have a ticket-tracking system that is not very 'user friendly' but I have a desire for my users to submit 'tickets' to the system without having them to see it.
I got as far as just using a custom HTTP Form and posting to the ticket tracking system. One problem is the 'success/completion' page has a tendency to confuse people. So I figured... well since I cant change the ticket system to use a different 'success' page. I will just handle the HTTP Post exchange with CURL and report a custom success or problem page. Heres some abstracted code.
File: tickethelper.php
<?php
extract($_POST);
$url = 'TICKETSYSTEMURL';
$fields = array(
'fullname'=>urlencode($fullname),
/*many more fields*/
);
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string,'&');
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
curl_setopt($ch, CURLOPT_MAXREDIRS, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$contents = curl_exec($ch);
curl_close($ch);
if((strlen(strstr($contents,'Your ticket has been submitted')))>0){
header("Location: http://THANKYOU");
}
else{
header("Location: http://OOPS");
}
?>
However, what I realized is that I am missing my file upload. Most of the CURL examples I have seen are to do with uploading local files to a remote HTTP POST page.
How do I handle receiving a file from my users HTTP form, process this in the 'tickethelper' and POST that to the 'TICKETSYSTEMURL' ?
-Israel
Well, I can't say I've done this myself, but according to the PHP documentation regarding CURL and File Handling (PHP.net)
CURLOPT_INFILE | The file that the transfer should be read from when uploading.
value should be a stream resource (using fopen(), for example) for the following values of the option parameter:
You should be able to call fopen() on the file that has been uploaded (refer to documentation regarding Handling File Uploads) I'm not sure, but you may need to call move_uploaded_file() to a controlled directory on the server before calling fopen()
For example:
$ch = curl_init();
$file = fopen($_FILES['file-field-name']['tmp_name'], 'r');
// OTHER CURL CONFIGURATION
curl_setopt($ch, CURLOPT_INFILE, $file);
curl_exec($ch);
First, your script can access the uploaded file through the $_FILES array.
From http://www.tizag.com/phpT/fileupload.php
The $_FILES array is where PHP stores
all the information about files. There
are two elements of this array that we
will need to understand for this
example.
uploadedfile - uploadedfile is the reference we assigned in our HTML
form. We will need this to tell the
$_FILES array which file we want to
play around with.
$_FILES['uploadedfile']['name'] - name contains the original path of the user uploaded file.
$_FILES['uploadedfile']['tmp_name'] -
tmp_name contains the path to the
temporary file that resides on the
server. The file should exist on the
server in a temporary directory with a
temporary name.
To include this file in the POST you send with libcurl, use an array of fields instead of a string. Include the file as one of the fields:
$post_fields = array (
$key => $value,
...
$file_key => "#" . $filename,
);
If you use the "#" symbol, libcurl will read the file and include it in the POST.
Then use
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);

Categories