Creating a link to download a .jpg file using PHP

It should be easy I think. I have a broken gallery of images and under each image there is a small link that says "Download Comp". This should allow users to quickly download the .jpg file (using the PHP generated watermark) to their computer.

Now I know I can just connect directly to the .jpg file, but this requires the user to open the image in a new window, right-click, "Save As ..." etc. Instead, I want "Download Comp" to start downloading the file immediately.

PHP.net seemed to suggest using readfile (), so every Download Comp link is repeated as "? Download = true & g = {$ gallery} & i = {$ image}".

Then at the top of the page I will catch to see if the $ _GET ['download'] var isset is there, and if so, I run the following code:

if(isset($_GET['download'])) {
$gallery = $_GET['g'];
$image = $_GET['i'];
$file = "../watermark.php?src={$gallery}/images/{$image}";
header('Content-Description: File Transfer');
    header('Content-Type: application/jpeg');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: public');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
readfile($file);

      

}

The link takes lonnnnnnnnnng time and then a dialog pops up asking to open or save the file, but as soon as you save it and try to open it, it says the file is corrupted and cannot be opened.

Any ideas?

+2


source to share


5 answers


Don't set $ file to a relative url. The readfile function will try to access the php file on the server. This is not what you want. In your case, it looks like the watermark.php file will send the content you want so you can just set up the environment it needs and enable it.

<?php
if(isset($_GET['download'])) {
    $gallery = $_GET['g'];
    $image = $_GET['i'];
    $_GET['src'] = "{$gallery}/images/{$image}";

    header('Content-Description: File Transfer');
    header('Content-Type: image/jpeg');
    header('Content-Disposition: attachment; filename='.basename($image));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: public');
    header('Pragma: public');
    ob_clean();
    include('../watermark.php');
    exit;
}

      

Another (easier) way is to change the watermark.php. Add a request parameter to send it to the appropriate headers to force the download and bind to it

<a href="watermark.php?src=filename.jpg&download=true)">...</a>

      



watermark.php:

<?php
if (isset($_GET['download']) && $_GET['download'] == 'true') {
    header('Content-Description: File Transfer');
    header('Content-Type: image/jpeg');
    header('Content-Disposition: attachment; filename='.basename($src));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: public');
    header('Pragma: public');
}
// continue with the rest of the file as-is

      

Also, you don't need a flush () call. There should be no output at this point, so this is optional.

+4


source


header('Content-Type: image/jpeg');

      



May be,?

+1


source


It looks like a security issue.

What to do if someone enters:

$g = '../../../../../../';
$i = '../../sensitive file at root';

      

How about creating a .htaccess (if you are using apache) i for the gallery directory serve jpegs up as upload, not ok.

+1


source


I think you might need to make a call readfile()

with a call exit()

to make sure nothing is written to the output buffer.

0


source


Also, try file_get_contents()

instead readfile()

. I believe this works under more circumstances. I also recommend using ob_flush()

post image data. I've never had to use ob_clean()

or flush()

to work at this level.

And as Eric said, you can also put the call exit()

where there is a good measure if it still doesn't work, in case you get some junk files stuck at the end.

0


source







All Articles