cbenjafield
cbenjafield

Reputation: 91

PHP force downloading .xlsx file corrupt

I am working on a site that allows teachers to upload documents and students download them. However, there is a problem. Microsoft Word (.docx) files download perfectly, but when downloading an excel (xlsx) file, excel gives a "This file is corrupt and cannot be opened" dialog. Any help with this would be greatly appreciated!

My download code is as follows:

case 'xlsx':

    header('Content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Content-Disposition: attachment; filename="' . $filename . '"');
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Pragma: no-cache');
    readfile('./uploads/resources/courses/' . $filename);

break;

Upvotes: 7

Views: 19874

Answers (6)

Felipe Buccioni
Felipe Buccioni

Reputation: 19668

I have this problem and was the BOM.

How to notice it

unzip: Checking the output file with unzip, I saw a warning at the second line.

$ unzip -l file.xlsx 
Archive:   file.xlsx
warning file:  3 extra bytes at beginning or within zipfile
...

xxd (hex viewer): I saw the first 5 bytes with the following command

head -c5 file.xlsx | xxd -g 1
0000000: ef bb bf 50 4b                             PK...

Notice the 3 first bytes ef bb bf that's BOM!

Why?

Maybe a BOM before the very first <?php tag on some php file or a previous output from a library.

You have to find where is the file or command with the BOM, In my case and right now, I don't have time to find it, but I solve this with output buffer.

<?php
ob_start();

// ... code, includes, etc

ob_get_clean();
// headers ...
readfile($file);

Upvotes: 4

boryn
boryn

Reputation: 876

Probably it's very misleading information given by Windows and has nothing to do with the code, Excel library, or server, and the file itself is a proper one. Windows blocks opening some files downloaded from the Internet (like .xlsx) and instead of asking whether you want to open an insecure file, it just writes that the file is corrupt. In Windows 10, one needs to right-click the file and select "Unblock" (you can read more for example here: https://winaero.com/blog/how-to-unblock-files-downloaded-from-internet-in-windows-10/)

Upvotes: 0

Elitmiar
Elitmiar

Reputation: 36829

Try adding a additional header

header('Content-Length: ' . filesize('./uploads/resources/courses/' . $filename));

Upvotes: 0

N. Peters
N. Peters

Reputation: 31

try:

<?
//disable gzip
@apache_setenv('no-gzip', 1); 
//set download attachment
header('Content-Disposition: attachment;filename="filename.xlsx"');
//clean the output buffer 
ob_clean(); 
//output file
readfile('filepath/filename.xlsx');
//discard any extra characters after this line
exit; 
?>

Upvotes: 1

cristi _b
cristi _b

Reputation: 1813

this works fine on my local xampp setup regardless of extension so from my point of view no case statement is needed unless i'm missing something

i've tested with docx, accdb, xlsx, mp3, anything ...

$filename = "equiv1.xlsx";

header('Content-type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Pragma: no-cache');

Upvotes: 2

GabCas
GabCas

Reputation: 788

try this:

header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Type: application/vnd.ms-excel");

Upvotes: 0

Related Questions