Reputation: 309
Im trying to make a script to download images from my localhost. Just for a schoolproject.
I get the filename via the url ("$_GET['file']"). Then i run this script. Every time the file is damaged and can't be viewed. I want to download images, but when i tried a word document it also was damaged. This is my code:
<?php
//get file
$file = $_GET['file'];
//set path of file
$path = $_SERVER['DOCUMENT_ROOT']."/blackbox/mediafiles/";
$fullPath = $path.$file;
if ($fd = fopen ($fullPath, "r")) {
$path_parts = pathinfo($fullPath);
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // fore a download
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
}
header("Cache-control: private"); // open files directly
while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
fclose ($fd);
exit;
?>
Anybody has and idea what goes wrong?
Thanks in advance!!
Upvotes: 1
Views: 1478
Reputation: 88647
Either something is throwing an error from PHP, or you have leading whitespace before the opening tag in the file (<?php
).
Do two things:
<
of <?php
is the first character in the file. Make sure your script doesn't have a byte order marker in it.error_reporting(0); ini_set('display_errors', 0);
Note that if disabling errors fixes your problem it means that there is an error which needs to be fixed, it is not a final solution to the problem!
Using readfile()
is also shorter, safer and more efficient than opening a file pointer and looping it.
Upvotes: 1
Reputation: 27285
At first its not your answer. But you should really look at Security in PHP. On Your script you can access all files over the GET Parameter and DOCUMENT_ROOT.
Don't trust a user.
You should filter your variables at first or map them with a known list of files before deliver them to a user.
Upvotes: 1
Reputation: 26699
You can use readfile instead of manually reading file and outputting.
Also, please note, that $_GET['file'] can contain '../' and open any file, which is a security risk. Use the basename function (if all files are in the same directory) or restrict access to files outside the mediafiles directory
<?php
//get file
$file = $_GET['file'];
//set path of file
$path = $_SERVER['DOCUMENT_ROOT']."/blackbox/mediafiles/";
$fullPath = $path. basename($file);
if (is_readable($fullPath) {
$path_parts = pathinfo($fullPath);
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // fore a download
header("Content-type: application/octet-stream");
header("Content-length: " . filesize($fullPath));
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
header("Cache-control: private"); // open files directly
readfile($fullPath);
}
exit;
?>
Upvotes: 1
Reputation: 7349
Try opening the file explicitly in binary mode:
if ($fd = fopen ($fullPath, "rb")) {
As the documentation on fopen states:
Windows offers a text-mode translation flag ('t') which will transparently translate \n to \r\n when working with the file. In contrast, you can also use 'b' to force binary mode, which will not translate your data. To use these flags, specify either 'b' or 't' as the last character of the mode parameter.
The default translation mode depends on the SAPI and version of PHP that you are using, so you are encouraged to always specify the appropriate flag for portability reasons. You should use the 't' mode if you are working with plain-text files and you use \n to delimit your line endings in your script, but expect your files to be readable with applications such as notepad. You should use the 'b' in all other cases.
If you do not specify the 'b' flag when working with binary files, you may experience strange problems with your data, including broken image files and strange problems with \r\n characters.
Upvotes: 3