PHP cannot output images - php

<?php
ob_clean();
header('Content-Type: image/jpeg');
header('Content-Length: ' . filesize($file));
$file = '111111-11111.jpg';
$handle = fopen($file, "r");
echo file_get_contents($file);
?>
At one point my php webpage stopped displaying all and any images I had successfully uploaded to MySQL database. I wanted to get down to the roots of this problem and see if it could output a .jpg image stored on HDD and all I get is the same output as when I'm trying access this image from database:
The image [...] could not be displayed because it contains errors.
The image location is correct, there are no whitespaces before header, the output buffer has been cleaned. I have spent days on google searching for the answer, but without luck.
I am quite new to PHP so if you can help, please be as descriptive as you can be, so I could understand.
Thank you in advance.

Be sure that the file you are trying to output is in the correct path (from the code, the same as the PHP script) and that you have the read permissions on the file.
$file = '111111-11111.jpg';
$type = 'image/jpeg';
header('Content-Type:'.$type);
header('Content-Length: ' . filesize($file));
readfile($file);

Related

Download with PHP readfile() works in Firefox, but not in Chrome

I am having a problem with my webpage. I am building a report tool for downloading data as .csv - I have a php skript which aggregates the data and builds a csv from it. The skript is invoked with the exec() command, detailed code is below. The skript itself uses file_put_contents() to generate the file, which is then stored in my /tmp/ folder until its downloaded (I am working in a dockerized environment and our filter rules delete the file at the next request, but I could store the file permanently somewhere else if that would be neccessary). I am then checking if the file is present with file_exists() and proceed to invoke my download function. In Firefox I get the desired result, a file with the correct content of only the csv data.
My main Problem is: When I download the csv in Chrome I get the csv data followed by the html source of my page - so starting with <!doctype html> in the first line after the csv data, then <html lang="de">in the next line of te csv and so on..
Let me show you some code:
In my skript:
private function writeToFile($csv)
{
$fileName = '/path/to/file' '.csv';
echo "\n" . 'Write file to ' . $fileName . "\n";
file_put_contents($fileName, $csv);
}
In my page class:
$filePath = '/path/to/finished/csv/'
exec('php ' . $skriptPath . $skriptParams);
if (file_exists($filePath)) {
$this->downloadCsv($filePath);
} else {
$pageModel->addMessage(
new ErrorMessage('Error Text')
);
}
My download function in the same class:
private function downloadCsv($filePath)
{
header('Content-Description: File Transfer');
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
header('Content-Length: ' . filesize($filePath));
readfile($filePath);
}
The shown above is working in Firefox, but not in Chrome. I already tried to clear the output buffer with ob_clean() or send and disable it with ob_end_flush() but nothing worked for Chrome.
I also tried something like this in my download function:
header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
$fp =fopen($filePath, 'rw');
fpassthru($fp);
fclose($fp);
This produces the same results in Firefox and Chrome - I get the csv data followed by the html sourcecode mixed into the same file.
I am working within a Symfony framework if that could be from help, I saw there are some helper functions for file downloads but I so far I could not use them with success..
Until now my target is only to get the download working in Chrome to have a working mvp which can go into production - it is supposed to be for internal use only, so I don't have to care about IE or some other abominations because our staff is told to use a normal browser... But when someone sees flaws in the general concept feel free to tell me!
Thanks in advance :)
So I managed to get it working, I was on the wrong track with the output buffer, but a simple exit()after my readfile()was enough to stop parts of the html ending up in the csv file.
Code:
private function downloadCsv($filePath)
{
header('Content-Description: File Transfer');
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
header('Content-Length: ' . filesize($filePath));
readfile($filePath);
exit;
}

mobi file corrupted after php download

I have some ebooks on my server, that I want people to be able to download. I uploaded them and when I download them via my ftp tool then everything is perfect. when I use my script for the user to download it, then I get the following error in calibre:
MobiError: Unknown book type: '\x00\x00\x00BOOKM'
my script that handles the output of the file is as follows:
$file_url = ABSPATH . $file['file'];
$basename = $story->post_title . $subtitle . '.' . $_POST['type'];
$filename = basename(mb_ereg_replace("([^\w\s\d\-_~,;\[\]\(\).])", '', $basename));
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-Disposition: attachment; filename=\"" . $filename . "\"");
readfile($file_url);
die();
Then all mobi readers I got say, that there is a problem with the file. I don't know what is going wrong. Also when I open the files in a text editor they are both different type. The one from my php script looks as follows:
the one that works from my ftp tool looks like this:
Anyone who can help me to find what I am doing wrong? The .epub files by the way are no problem with my script.
I solved this problem by outputting the file as follows:
ob_clean();
flush();
readfile($path);
exit;

Corrupted images when downloading from RapidShare

I offload a lot of my sites uploads to RapidShare for storage. I then have a script that when accessed by a user wanting to download a file, downloads it from RapidShare using their API and serves it to the user. Here's the relevant code in the script that serves the file:
// Stream file to user
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename=' . $result->name);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Content-Length: ' . $result->size);
$url = 'https://' . $host . '/cgi-bin/rsapi.cgi?sub=download';
$url .= '&login=login';
$url .= '&password=mypass';
$url .= '&fileid=' . $result->rs_fileid;
$url .= '&filename=' . $result->name;
$handle = fopen($url, 'rb');
if(!$handle) {
throw new Exception('Failed to open file handle');
}
while(!feof($handle)) {
echo fread($handle, 1024*1024);
ob_flush();
flush();
}
fclose($handle);
This works fine for all the files I've tested except for images. When the images are downloaded, they're corrupt. Windows Photo Viewer can't open the image and neither can programs like Photoshop.
Weird thing is, if I download a .exe and run it, everything works fine. It's not corrupt. It only happens with images as far as I can tell. I've also tested it with .pdf's.
To make it weirder, if I look at the filesize of the original image (2,882 bytes) and then the filesize of the image downloaded through this script, they're the same. The filesizes for both are 2,882 bytes. But the image is still corrupt.
What could be the cause of this and the solution? It's not like I'm adding any binary data to the file as it's downloaded. :/
Thanks.
Edit: Forgot to mention, if I download the file straight from RapidShare without going through the script the image is fine and isn't corrupt. So it must be the script at fault here.
Check my answer for a similar problem, I'm pretty sure there will be some notice at the beginning of your files!
Simplify your code, there is no need for the header() stuff and file_put/get_contents is much sleeker:
$url = 'https://' . $host . '/cgi-bin/rsapi.cgi?sub=download';
$url .= '&login=login';
$url .= '&password=mypass';
$url .= '&fileid=' . $result->rs_fileid;
$url .= '&filename=' . $result->name;
file_put_contents($result->name, file_get_contents($url));
When you have memory problems, use mod_xsendfile, easy to use.

How to serve a .dmg file via PHP/readfile?

I'm having no luck serving a .dmg from my online store. I stripped down the code to just the following to debug, but no matter what I get a zero-byte file served:
header('Content-Type: application/x-apple-diskimage'); // also tried octet-stream
header('Content-Disposition: attachment; filename="My Cool Image.dmg"');
$size = filesize('/var/www/mypath/My Cool Image.dmg');
header('Content-Length: '.$size);
readfile('/var/www/mypath/My Cool Image.dmg');
This same code works for a number of other file types that I serve: bin, zip, pdf. Any suggestions? Professor Google is not my friend.
Found the solution. The culprit was readfile() and may have been memory related. In place of the readfile() line, I'm using this:
$fd = fopen ('/var/www/mypath/My Cool Image.dmg', "r");
while(!feof($fd)) {
set_time_limit(30);
echo fread($fd, 4096);
flush();
}
fclose ($fd);
It's now serving all filetypes properly, DMG included.
You should not have spaces in the filename (Spaces should not be used when it comes to web hosted files)
Try something like this or rename your file with no spaces:
<?php
$path ='/var/www/mypath/';
$filename = 'My Cool Image.dmg';
$outfile = preg_replace('/[^a-zA-Z0-9.-]/s', '_', $filename);
header('Content-Type: application/x-apple-diskimage'); // also tried octet-stream
header('Content-Disposition: attachment; filename="'.$outfile.'"');
header('Content-Length: '.sprintf("%u", filesize($file)));
readfile($path.$filename); //This part is using the real name with spaces so it still may not work
?>

PHP redirect without change current url?

We have some mp3 file collection and flash player used this mp3 file, to track mp3 file listing we render mp3 file using php file below is code
http://www/example.com/getFile.php?fileid=12
<?php
$id = $_REQUEST['fileid'];
// Some code to store download traking and get filename for this id in $filename var.
$filename = getFileName($id);
header('Content-type: audio/mpeg');
header('Content-Disposition: filename=' . $id . '.mp3');
readfile($filename);
?>
But mp3 file size in very big and player get break in IE, for that we also use below code
<?php
$id = $_REQUEST['fileid'];
// Some code to store download traking and get filename for this id in $filename var.
$filename = getFileName($id);
header('Location: '. $filename);
?>
this code working fine but its also chnages current URL
i.e http://www/example.com/getFile.php?fileid=12 to http://www/example.com/files/xyz.mp3
so user can easily download mp3 file direct how i prevent this? using php or other way ?
Let Flash fetch the file. Return just the URL to Flash through the PHP.
(Sorry, didn't read the question properly when I originally posted - I see now that the problem is with IE and large file size)
You could try telling IE the length, and flushing the buffers:
header('Content-Length: ' . filesize($file));
ob_clean();
flush();

Categories