1

i though i found the answer here: Serving .docx files through Php But i am still getting the error that the file is corrupt when trying to download and open a docx server via php Maybe you can see something wrong with my code. The .doc works fine it is the docx that fail.

$parts = pathinfo($doc);
$docFile = $userDocRoot.$doc;
if ( !file_exists($docFile) ){
    throw new Exception("Can not find ".$parts ['basename']." on server");
}
if ( $parts['extension'] == 'docx' ){
    header('Content-type: application/vnd.openxmlformats- officedocument.wordprocessingml.document');
    header('Content-Disposition: attachment; filename="'.$parts['basename'].'"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    ob_clean();
    flush();
    readfile($docFile);
}else{
   header('Content-type: application/msword');
   header('Content-Disposition: attachment; filename="'.$parts['basename'].'"');
   readfile($docFile);
}
Community
  • 1
  • 1
randy
  • 1,685
  • 3
  • 34
  • 74

5 Answers5

3

The solution for me was to add

 $fsize = filesize($docFile);
 header("Content-Length: ".$fsize);

Thanks for everyones help

randy
  • 1,685
  • 3
  • 34
  • 74
2

There were a few extra spaces in your code which would cause it to fail.

Try using this code:

$parts = pathinfo($doc);
$docFile = $userDocRoot . $doc;
if(!file_exists($docFile)){
    throw new Exception('Can not find ' . $parts['basename'] . ' on server');
}
if($parts['extension'] == 'docx') {
    header('Content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
    header('Content-Disposition: attachment; filename="' . $parts['basename'] . '"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    ob_clean();
    flush();
    readfile($docFile);
} else {
    header('Content-type: application/msword');
    header('Content-Disposition: attachment; filename="' . $parts['basename'] . '"');
    readfile($docFile);
}

If it still doesn't work, try commenting out the header and the readfile lines, then you will see if there are any errors.

Also, I suggest that you check the filenames against a whitelist, so that people can't download PHP files with passwords in them, etc.

uınbɐɥs
  • 7,236
  • 5
  • 26
  • 42
  • no difference :-( no errors when i comment out header and readfile – randy Aug 21 '12 at 20:28
  • @randy What happens if you don't comment out the `readfile` line? Also, if you open the resulting file in Notepad, do you see any errors? – uınbɐɥs Aug 21 '12 at 20:31
  • if i comment out everything but the readfile, i get a bunch of unprintable characters on the page, which makes sense since it is a doc file i guess. – randy Aug 21 '12 at 20:35
  • Can you try creating a test document, save it as a `docx`, and access it through your script? – uınbɐɥs Aug 21 '12 at 20:39
  • @randy Okay. Try accessing it directly though your web browser. – uınbɐɥs Aug 21 '12 at 20:40
  • when i did it in java i went through the same hassle. One thing i had to do it java was response.setContentLength((int) file.length()); Is there something similar in PHP. I assume there is – randy Aug 21 '12 at 20:41
  • Use `header('Content-Length: ' . filesize($docFile));`. – uınbɐɥs Aug 21 '12 at 20:46
1

I have just spent a while looking at why my DOCX files are being corrupted and stumbled across this... but I have also found the answer elsewhere...

$fsize = filesize($docFile);
header("Content-Length: ".$fsize);

This gave me the tools to look for... and the key is that filesize() needs the basename of the file to get an accurate file size!

Adapting my code:

header("Content-Length: ".filesize(basename($file)));

This now offers DOCX (I have set the Content-type to "application/vnd.openxmlformats-officedocument.wordprocessingml.document") as intended and I do not have to "repair" the document like others have reported... (I also found that repairing worked)

Kinnectus
  • 899
  • 6
  • 14
  • This is the correct answer. I just specified `Content-type` and `Content-Disposition`. Adding `Content-Length` solved the problem. Thanks! – Matt Komarnicki Feb 11 '16 at 10:04
0

Here is a code that's working for me (after about 5 hours of messing around):

           // headers to send your file
           header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
           header("Content-Length: " . filesize($original_file));
           header('Content-Disposition: attachment; filename="' . $new_filename . '"');
           ob_clean();
           flush();
           readfile($original_file);
           exit;

I hope it helps :)

Fery Kaszoni
  • 3,956
  • 1
  • 18
  • 11
-2

I had the same issue.

The reason was, that somewhere in my php-file two spaces were hidden.

Removing them fixed the issue.

  1. Add "//" in front of the header and readfile-statements
  2. Write echo "test"; after the readfile-statement.
  3. Then look in the HTML source-code, if there are spaces in front of the "test".
Moses Davidowitz
  • 982
  • 11
  • 28