Forum Moderators: coopster

Message Too Old, No Replies

Strange corrupted downloads?

PHP downloads corrupted

         

helmet

4:34 pm on Jun 17, 2004 (gmt 0)

10+ Year Member



I have two functions uploading and downloading files to/from a mediumblob mysql field. Somehow my downloaded files were being corrupted, and I've managed to isolate the problem to the appearance of a single space in the first character of the downloaded file. For example a .doc file won't open in Word, so I open it with a plain text editor and remove the first character (a space), save, then it opens fine in Word.

I have been pulling my hair out for two days (sad, I know) trying to figure out where this problem is originating from. At this point I am desperate for a solution! Here is the code for upload:

        $data = fread(fopen($file['tmp_name'], "r"), filesize($file['tmp_name']));        
        $data = base64_encode($data);
        $file_name = $name;
        $file_size = filesize($file['tmp_name']);
        $file_type = $file['type'];
        $insert = db_query("insert into files (id, bin_data, file_name, file_size, file_type) values('$this->pid', '$data', '$file_name', '$file_size', '$file_type')");

and download:

$query = @db_query("SELECT bin_data, file_type, file_name, file_size FROM files WHERE id = '$file_id'"); 
    $result = db_fetch_object($query);
    $file = base64_decode($result->bin_data);
    header("Content-type: application/octet-stream");
    header("Content-Disposition: attachment; filename=$result->file_name");
    header("Content-length: $result->file_size");
    
    print $file;

I tried going back from PHP 4.3.7 to 4.3.4, but the problem persists. I thought it might be a bug. I am completely lost on this problem. Any ideas would be greatly appreciated!

jdMorgan

5:24 pm on Jun 17, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



helmet,

I don't think Content-type: application/octet-stream is the correct MIME-type for an MS-Word file, so IE will revert to examining the content itself to try to figure our what kind of file it is and how to handle it. If the initial few bytes don't exactly match any of IE's 'templates' for various filetypes, it'll just treat it as text/html, and you'll get the 'raw' data printed out in the browser window.

The root problem is this rogue space character -- where is it coming from? The MIME-type problem just makes it worse, and will cause more problems in non-IE browsers, which strictly abide by the Content-type specified in the header. I think you should try deriving the correct filetype from your database field, and inserting it into the Content-type header. But again, where's the extra space character coming from?

Jim

helmet

5:37 pm on Jun 17, 2004 (gmt 0)

10+ Year Member



Hi Jim, thanks for replying.

The reason I'm using application/octet-stream is to force download (I've tested it in IE/Win and other browsers on Mac and it doesn't display in the browser window) which is a solution I've seen on various boards. I also have .txt and image files uploaded, and I want to ensure these are downloaded and not viewed directly in the browser.

The rogue space character in .doc and .xls files (and all others... images and txt as well) seems to remain whether I use the correct filetype or octet-stream.

I tried using

print substr($file, 1);

but this strips the first character AFTER the space! It gives a clue that the problem is not with my code, but it doesn't seem to be with the filetype either.

helmet

3:37 am on Jun 18, 2004 (gmt 0)

10+ Year Member



pdf and txt files open ok despite the space, but examining a jpg in a text editor with the original that I uploaded, I found not only a space at the start of the file, but a missing character at the end which once copied and pasted into the downloaded copy allowed it to open as a jpg.

Can anyone shed some light on this? I'm scanning all uploads for virii with ClamAV.. could this have anything to do with it? I wouldn't think so because this is done before storing in the DB..

jdMorgan

4:32 am on Jun 18, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



It sounds like a data "alignment" problem in the db... Does the database have configuration options to specify 8, 16, or 32-bit storage of data elements? How about big-endian versus little-endian addressing? If these options are available and set incorrectly for the machine architecture, you could end up with this kind of "off by one" error.

Jim

helmet

5:19 am on Jun 18, 2004 (gmt 0)

10+ Year Member



I'm using MySQL 4.0.18 and I've just done some searching for information on this topic but I'm not finding anything that makes sense to me. Can you suggest steps to take or places to look?

Thanks in advance!

helmet

4:56 pm on Jun 18, 2004 (gmt 0)

10+ Year Member



I just downgraded MySQL to 3.23.56 on the server (Red Hat 9), to no avail. I assumed, since I have no idea how to configure bits and endians, that a fresh install with the version I originally wrote the code under might eliminate the problem, but it did not.

Tthis is an area I have not been aware of until now so please excuse my ignorance... I had a look at mbstring functions in PHP. Are they relevant?

helmet

6:34 pm on Jun 18, 2004 (gmt 0)

10+ Year Member



I figure it might be helpful to someone else to have the benefit of my findings... sorry for carrying on a thread all alone ;)

I have just done some tests. I uploaded the file to the server and wrote it immediately to a temporary file to see if the rogue shift was taking place between the upload and base64_encoding to save to the database. There was no rogue space. Then I wrote another temp file after downloading it from the database and base64_decoding.. again, no rogue space. The shift in the file content is occuring sometime during the actual copying of the file to the remote machine.

One thing I have noticed is that if I exclude the header pertaining to filesize, the HTML of the page that loads after the download is included in the content of the file. I'm not sure if this is causing the space at the start of the file though..

Weeeee how fun.

helmet

5:41 pm on Jun 19, 2004 (gmt 0)

10+ Year Member



This problem has been solved. I had made sure that the file containing the DL code had no whitespace outside the <? and?> tags, but I overlooked my application.php file (included on all my pages) which links to several other files. Two of those had a little whitespace after the closing PHP tag. A stupid oversight.