topcoder1 Posted August 24, 2007 Share Posted August 24, 2007 I am streaming some files from the database and serve it over http, for text files and even pdf files it works, but for image files and xls files the files seem to be corrupted. For testing purpose, after I grab the file from the blob field in mysql db, I write it to a file on the server which looks good by manual inspection. However when the user downloads and opens the file it's corrupted. For xls, there are bunch of binary codes scattered around with texts. For image file it simply can't be viewed. What's wrong?? function html_item_file($item_id){ $this->init_db(); $query="..."; if($res=mysql_query($query)){ $item=mysql_fetch_assoc($res); $file=$item['file_content']; $file_name=html_entity_decode($item['item']); $file_len=$item['file_len']; error_log("file is ".$file_name.", ".$file_len); error_log("q is ".$query); //extract raw and save to file, this result file looks good /* $handle = fopen("c://temp//output//".$file_name, 'w'); fwrite($handle, $file); fclose($handle); */ $this->stream_file($file_name, $file_len, $file); } } function stream_file($filename, $file_len, $file){ header("Content-Disposition: inline; filename=\"".$filename."\""); header("Content-Type: image/png");//application/octet-stream // header("Content-Length: ".$file_len); header("Pragma: no-cache"); header("Expires: 0"); echo $file; exit(); } Quote Link to comment https://forums.phpfreaks.com/topic/66435-stream-image-files/ Share on other sites More sharing options...
MadTechie Posted August 24, 2007 Share Posted August 24, 2007 first the file type is always set to PNG header("Content-Type: image/png" also i don't think echo in binary safe, maybe use convert_uuencode/convert_uudecode Quote Link to comment https://forums.phpfreaks.com/topic/66435-stream-image-files/#findComment-332597 Share on other sites More sharing options...
topcoder1 Posted August 24, 2007 Author Share Posted August 24, 2007 first the file type is always set to PNG header("Content-Type: image/png" also i don't think echo in binary safe, maybe use convert_uuencode/convert_uudecode thanks for the help. I tried using header application/octet-stream and base64_encode since convert_uuencode is a php5 function and I use php4. still doesn't help. Image gets downloaded then can't be opened. function stream_file($filename, $file_len, $file){ header("Content-Disposition: inline; filename=\"".$filename."\""); header("Content-Type: application/octet-stream");// // header("Content-Length: ".$file_len); header("Pragma: no-cache"); header("Expires: 0"); print base64_encode($file); exit(); } Quote Link to comment https://forums.phpfreaks.com/topic/66435-stream-image-files/#findComment-332627 Share on other sites More sharing options...
MadTechie Posted August 24, 2007 Share Posted August 24, 2007 what about this keep the //extract raw and save to file, this result file looks good /* $handle = fopen("c://temp//output//".$file_name, 'w'); fwrite($handle, $file); fclose($handle); */ then use readfile($filename); instead of echo'ing the data.., then after the steaming unlink($filename) as for the header("Content-Type: application/octet-stream");// try this instead header("Content-Type: application/force-download");// NOTE: header("Content-Type: application/octet-stream");// will probably fail in IE IEs version is header("Content-Type: application/octetstream");// Quote Link to comment https://forums.phpfreaks.com/topic/66435-stream-image-files/#findComment-332638 Share on other sites More sharing options...
chronister Posted August 24, 2007 Share Posted August 24, 2007 just out of curiosity, why are you actually storing the image in the database? Why not store the name of the file in the database and then store the actual file in the file system? It seems to me that this would be easier and less chance of file corruption. Nate Quote Link to comment https://forums.phpfreaks.com/topic/66435-stream-image-files/#findComment-332690 Share on other sites More sharing options...
topcoder1 Posted August 24, 2007 Author Share Posted August 24, 2007 Ok I tried outputting to a temp file, then readfile(), still after I download the file, i can't open it. But I view the temp file on server and it's fine. the temp file and the file I DL are the same size. What is going on?? I am using FF. something's very bizzare here... $handle = fopen("c://temp//output//".$file_name, 'w'); fwrite($handle, $file); fclose($handle); /* $handle=fopen("c://temp//output//".$file_name, 'rb'); error_log("fread ".fread($handle, filesize("c://temp//output//".$file_name))); fclose($handle); */ $this->stream_file($file_name, $file_len, $file); } } function stream_file($filename, $file_len, $file){ header("Content-Disposition: inline; filename=\"".$filename."\""); header("Content-Type: application/octet-stream");// // header("Content-Length: ".$file_len); header("Pragma: no-cache"); header("Expires: 0"); //print base64_encode($file); error_log("file name is ".$filename); error_log("file read ".readfile("c://temp//output//".$filename)); exit(); } Quote Link to comment https://forums.phpfreaks.com/topic/66435-stream-image-files/#findComment-332705 Share on other sites More sharing options...
topcoder1 Posted August 24, 2007 Author Share Posted August 24, 2007 just out of curiosity, why are you actually storing the image in the database? Why not store the name of the file in the database and then store the actual file in the file system? It seems to me that this would be easier and less chance of file corruption. Nate I am just trying out this way to see how it will work. I know there's a whole debate of db vs flat file going on... Anyway debugging to this point it seems that it's unrelated to db, the server reads from a flat file and then stream it to client, but the file is corrupt after DL... maybe I'm just insane here... Quote Link to comment https://forums.phpfreaks.com/topic/66435-stream-image-files/#findComment-332714 Share on other sites More sharing options...
topcoder1 Posted August 24, 2007 Author Share Posted August 24, 2007 OK I FINALLY FIGURED IT OUT. You guys would not believe what's the cause of the problem.. It's not the db, not even the streaming function... I had a funny feeling something as obscure as this is the problem. case 1: it works <?php require_once "item.php"; $item=new Item(); $item->test_stream_file(); //stream a file over http ?> case 2: it corrupts the file!! <?php require_once "item.php"; ?> <?php $item=new Item(); $item->test_stream_file(); ?> It seems that when closing and restarting the php tag something is send over http that messed the file download up. Who would have thought!!! thanks all Quote Link to comment https://forums.phpfreaks.com/topic/66435-stream-image-files/#findComment-332742 Share on other sites More sharing options...
topcoder1 Posted August 24, 2007 Author Share Posted August 24, 2007 Ok I was a little quick on making the conclusion about php tag. The root of all evil is the empty lines before the php tag starts the blank lines before <?php are being sent as part of the server response to the client. In my case, my include class had blank lines in the beginning and these lines are sent back to the client as part of the download, hence caused the problem. I am still vague as to why that caused the download problem since those blank lines are sent before the http headers and the file data itself, but I'm beat and need some sleep. my working test code follows, if I add any blank lines before any of those php starting tags, it will break. test.php <?php require_once "Streamer.php";?> <?php $a=new Streamer(); $a->stream_file("test.jpg", "c://temp//output//test.jpg"); ?> Streamer.php <?php class Streamer{ function stream_file($filename, $file, $file_len=null){ header("Content-Disposition: inline; filename=\"".$filename."\""); header("Content-Type: application/force-download");//octet-stream if($file_len!=null)header("Content-Length: ".$file_len); header("Pragma: no-cache"); header("Expires: 0"); readfile($file); exit(); } } ?> Quote Link to comment https://forums.phpfreaks.com/topic/66435-stream-image-files/#findComment-332771 Share on other sites More sharing options...
chronister Posted August 24, 2007 Share Posted August 24, 2007 Blank lines aka whitespace is the same as text as far as a webserver is concerned. All headers MUST be sent before anything else. If any output is sent to the browser before the headers are sent, you will generally get a Header error. You can circumvent this by using ob_start() at the top of the page and ob_end_flush() at the end, this will buffer all output and send it all at once in the end after the headers have been sent. Quote Link to comment https://forums.phpfreaks.com/topic/66435-stream-image-files/#findComment-332975 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.