2

I try to use php to force the image jpg file download, I have implemented eth following code:

html

<a href = "filedownload.php?src=uploads/myimage.jpg&download=true>download this file</a>

download.php

 <?php
ob_start();
 include_once 'functions.php';

if (isset($_GET['download']) && $_GET['download'] == 'true')
  {    

  $src = sanitizeString($_GET['src']);
  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');

  } 

 ?>

Suppose the full path of the image is "www.example.com/smith/topic/uploads/myimage.jpg", I have recieved the right image name and the download window is appeared as well, but the image is corrupt and with 1KB size, any one could tell me why, thanks a lot.

smith
  • 5,341
  • 8
  • 31
  • 38
  • What's inside the file? I'll bet a beer there's a PHP error message in it that explains what went wrong. – Pekka Oct 01 '11 at 16:40
  • which code? thant's all I've got for that part – smith Oct 01 '11 at 16:41
  • For one thing, there's a space at the start of the PHP script, which is a no-no. You also forgot a " at the end of your href. Are you even printing the file contents in there? PS: I would strongly recommend handling files like this. There are just way too many places for a potential attack. –  Oct 01 '11 at 16:41
  • @smith well, where are you actually outputting the file's data? – Pekka Oct 01 '11 at 16:42
  • try yo `var_dump(basename($src))` and check if this is fill path to image?! – Faraona Oct 01 '11 at 16:43
  • @Kevin, sorry I am new to php, can you tell me how to do it – smith Oct 01 '11 at 16:45

3 Answers3

6

Here you are example how to use readfile function

<?php
$file = 'monkey.gif';

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
}
?>
Faraona
  • 1,685
  • 2
  • 22
  • 33
1

You need some code that actually sends over the file. See e.g. readfile or fpassthru

nos
  • 223,662
  • 58
  • 417
  • 506
  • @smith Place it before the last brace. You might also want to check if the file is actually in the directory, just incase an attacker uses your script to read something outside of it (e.g. `/../../../../etc/passwd`) –  Oct 01 '11 at 16:48
  • do you mean place it after basename($file)? – smith Oct 01 '11 at 16:52
  • after `header('Pragma: public');` –  Oct 01 '11 at 16:55
  • so the code for send over the file is in the link you provided? – smith Oct 01 '11 at 17:01
  • @smith Both links contain examples (either in the description or comments) on how to send files as an attachment. – nos Oct 01 '11 at 17:13
  • thanks, I solved it, but still don't know how to prevent the attacker using my script to read somthing outside, is there an example explain it. – smith Oct 01 '11 at 17:19
1

Try to use:

header("Content-Disposition: attachment; filename=\"".basename($fullPath)."\";" );
Faraona
  • 1,685
  • 2
  • 22
  • 33