4

The snippet reads an ouput stream in a new file CSV. That part works. I can open the file from the server and it looks perfect. The problem is with the file which downloads to my hard drive through the browser. It will not open and read properly in spreadsheet software or Excel on a Windows machine:

$NewFile = fopen($FileName,"w");
fwrite($NewFile, $output);
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$FileName.'"'); 
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($NewFile));
ob_clean();
flush();
readfile($NewFile);

The content of the CSV looks ��ࡱ� like when I open it from the browser download but looks perfect when I open it directly on the server or download the stored file with FTP.

3
  • Have you tried reading it through your browser, without trying to download it? That could tell you if it's your file being messed up by your browser, or if your download code is damaging something. Commented Aug 30, 2012 at 1:28
  • 1
    Since its a csv should not the encoding be Content-Type: text/plain or even text/csv Commented Aug 30, 2012 at 1:33
  • 1
    @AdrianCornish I believe you're right. Being a plain text file, regardless of it's extension and how programs interpret it, it is just text, and should be saved accordingly. Commented Aug 30, 2012 at 1:34

1 Answer 1

4

The browser sees the application/octet-stream as a binary type. You need a text/plain content type:

header('Content-Type: text/plain');
// Or:
header('Content-Type: text/csv');
// Or: 
header('Content-Type: application/csv');

The Content-Transfer-Encoding header should be unnecessary if you have the Content-Type correctly set, and indeed it is probably misleading the browser into thinking it has received a binary file as well:

// No need, possibly harmful. Remove it...
// header('Content-Transfer-Encoding: binary');

###Update:

I see another problem. You are setting the Content-Length not to the size of the file, but rather to the file handle opened by fopen(), which mis-informs the browser of the number of bytes to expect. filesize() takes a string filename as its argument, not a file handle. You will probably need to close the handle with fclose($NewFile) before calling filesize().

// Instead of:
header('Content-Length: ' . filesize($NewFile));

// You mean to use $FileName
// close the file handle first...
fclose($NewFile);
header('Content-Length: ' . filesize($FileName));
Sign up to request clarification or add additional context in comments.

5 Comments

I tried both application/csv and text/csv - have not tried text/plain but will.
I would try with header('Content-Type: text/csv; charset=utf-8');
I think I'm just trying things now and not sticking with my knowledge - probably should pick it up again tomorrow but this is the last thing I need to finish this plugin. Based on what we have said here I now have: $NewFile = fopen($FileName,"w"); fwrite($NewFile, $output); header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename="'.$FileName.'"'); fclose($NewFile); header('Content-Length: '.filesize($FileName)); Same results. File on server is fine but browser is not. I'm beginning to wonder if there is something in the .htaccess file or config.
Here is a documentation you can read about the encoding, because, far has I know it's an encoding problem : webmonkeyuk.wordpress.com/2011/04/23/…
Thanks everyone. I think I just need to get some rest and open it again tomorrow. I agree with @JonathanLaf that it looks like an encoding problem while it's outputting to the browser.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.