Copying Images with allow_url_fopen Switched Off

I’m working on a Facebook app that needs to collect images from an external server. Normally I could use a function like copy to do this, but this requires allow_url_fopen to be on and a lot of providers like mine have this turned off to tighten server security.

Eventually I came across file_get_contents to do the job. Since this also needs allow_url_fopen to be on, my post on fetching page content with cURL came to mind.

This does the same thing without restrictions on privacy and is available on most current setups.

Fetching Raw Data with get_page_content

We start off with our get_page_content method from the last post, which we use to collect page data. We’re looking to collect the raw data of an image, and here I’ve used the Google logo as an example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function get_page_content($url)
{
  $resource = curl_init();
 
  curl_setopt($resource, CURLOPT_URL, $url);
  curl_setopt($resource, CURLOPT_HEADER, false);
  curl_setopt($resource, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($resource, CURLOPT_CONNECTTIMEOUT, 30);
 
  $content = curl_exec($resource);
 
  curl_close($resource);
 
  return $content;
}
 
$content = get_page_content('http://www.google.co.uk/intl/en_com/images/srpr/logo1w.png');
 
$fp = fopen('logo.png', 'w');
fwrite($fp, $content);
fclose($fp);

The use of get_page_content is the same as in the last post.

For the last three lines we use a few functions for creating a new file.

The first line creates a handle to a file (which doesn’t have to exist), which here we’ve called “logo.png”. This is where our image will be copied to. The “w” parameter tells the script we are opening the file for it to be directly written to, and we save the resource into $fp.

The second line writes the content that we collected earlier into our image. The raw data will make it display properly since it’s being saved as an image file.

Calling fclose on the resource closes the handle to it and frees up memory.

Mimicking the PHP Copy

Now the script will work fine if you use it as-is, but for a more robust way of handling file copying we’re going to create a wrapper around it to be called similarly to the copy function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function copy_file($source, $destination)
{
  $resource = curl_init();
 
  curl_setopt($resource, CURLOPT_URL, $source);
  curl_setopt($resource, CURLOPT_HEADER, false);
  curl_setopt($resource, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($resource, CURLOPT_CONNECTTIMEOUT, 30);
 
  $content = curl_exec($resource);
 
  curl_close($resource);
 
  $fp = fopen($destination, 'w');
  fwrite($fp, $content);
  fclose($fp);
}

Here we have a new function with a $source and $destination parameter, identical to copy.

Handling Failed Requests

To add even further similarity to the allow_url_fopen method I’ll add in some boolean return values.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function copy_the_file($source, $destination)
{
  $resource = curl_init();
 
  curl_setopt($resource, CURLOPT_URL, $source);
  curl_setopt($resource, CURLOPT_HEADER, false);
  curl_setopt($resource, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($resource, CURLOPT_CONNECTTIMEOUT, 30);
 
  $content = curl_exec($resource);
 
  curl_close($resource);
 
  if($content != '')
  {
    $fp = fopen($destination, 'w');
    $fw = fwrite($fp, $content);
    fclose($fp);
 
    if($fw != false)
    {
      return true;
    }
  }
 
  return false;
}

So now if there is no content in the external file or the new file can’t be written to your server, the function will return false.

You can add to this with some cURL error checking and a handler on fopen, but it depends how robust it would need to be on your own website.

The great thing is, this script doesn’t just work with images. Just change the destination file to anything else with a change of extension and it’ll work exactly the same.


2 thoughts on “Copying Images with allow_url_fopen Switched Off

Comments are closed.