I have some code that takes a URL and downloads it using CURL. Here's the code:

            $url= $row['loc'];
            $path = 'tmp/';
            $path .= rand(100,999);
            $path .= $row['name'];
            $fp = fopen($path, 'w');
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_FILE, $fp);     
            $data = curl_exec($ch);     
            curl_close($ch);
            fclose($fp);

            $downloadarray[] =  array($path, $row['name']);

However the file is not correctly downloading as an image even though the filename is, for example paradise-island.jpg. Do I need to specify a minetype somewhere? I belive this is also causing problems further down the code, because despite the fact this code is run twice on separate files this code:

foreach ($downloadarray as $file) {
            $zip->addFile($file['0'], $file['1']);
}

is only adding one file to a zip. Does anybody have any ideas? Thanks!

However the file is not correctly downloading as an image

Can you confirm that the size of $data matches the file size of the original image? I think it also contains header information of the response. What exactly are you writing to the file? There's no fwrite in the above snippet.

That may have something to do with it...
Checking that now

Okay, file is 336kb which sounds right for an image and not just headers. I've added fwrite and my code now looks like this. On my mac, get info is correctly rendering a preview, it's just the actual file itself is not a jpeg even though it should be.

            $url= $row['loc'];
            $path = 'tmp/';
            $path .= rand(100,999);
            $path .= $row['name'];
            $fp = fopen($path, 'w');
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_FILE, $fp);     
            $data = curl_exec($ch);     
            curl_close($ch);
            fwrite($fp, $data);
            fclose($fp);

            $downloadarray[] =  array($path, $row['name']);

Do print_r($data); and see what it contains. Perhaps there's more than just the file.

No ideas left atm. Am sure somebody else will chip in.

Is there any way of setting the type of file via PHP. The file is correctly downloading and contains everything it should but it doesn't have the mimetype of a JPG

Files don't have mime types, there are two factors: The file extension, and the header in an image file that contains information about the image type. I assume you're referring to the latter?

If the image is actually a jpeg ( http://www.php.net/manual/en/function.exif-imagetype.php can tell you ) then saving it as a .jpg should work. If you for some reason need to actually change the internal header, GD is probably your best bet but it's rather resource-intensive for what you're doing.

Fixed one bug, apparently I don't need fwrite as curl is writing. However the download is now broken, the zip file doesn't encrypt properly. And the files are also zero bytes. Here's the updated code (added a bit more than first snippet)

if ($_GET['download']== 'true'){
          $downloadarray = array();
          while($row = mysql_fetch_array($res)){
            $url= $row['loc'];
            $path = 'tmp/';
            $path .= rand(100,999);
            $path .= $row['name'];
            $fp = fopen($path, 'w');
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_FILE, $fp);     
            $data = curl_exec($ch);     
            curl_close($ch);
            fclose($fp);
            echo print_r($data);
            $downloadarray[] =  array($path, $row['name']);
          }

        //this stuff is not included in the OP
         $zipname = rand(0,9999) . 'download.zip';
          $zip = new ZipArchive;
          $zip->open($zipname, ZipArchive::CREATE);
          foreach ($downloadarray as $file) {
            $zip->addFile($file['0'], $file['1']);

          }
          $zip->close();
          header('Content-Type: application/zip');
          header('Content-disposition: attachment; filename=' . $zipname);
          header('Content-Length: ' . filesize($zipname));
          readfile($zipname);
          unlink($zipname);

        }

I believe you need to set CURLOPT_RETURNTRANSFER before CURLOPT_FILE:

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FILE, $fp);