PHPExcel導出格式錯誤問題--格式與文件擴展名格式不一致--解決方案

使用PHPExcel自身simple導出沒問題,複製到個人代碼中再導出就會出現「您嘗試打開的文件1.xls的格式與文件擴展名指定的格式不一致...」。php

經過排查問題發現幾點差別:web

1.我直接調用乾淨的導出代碼正常,在調用導出代碼前調用了$table=D("someAction");就會出問題(ThinkPHP),其餘代碼包括M()->query("select ....");以及其餘簡單代碼都不會致使導出錯誤。app

2.Excel生成到本地後FTP出來正常,直接經過web導出下載就會出問題。google

3.比較正常和不正常的xls文件,正常excel文件開頭爲D0 CF 11,而導出錯誤的文件在文件頭多了3個字節:EF BB BF。。。這是爲何呢?編碼

google發現一個相關信息,utf-8的BOM:spa

UTF- 8以字節爲編碼單元,沒有字節序的問題。UTF-16以兩個字節爲編碼單元,在解釋一個UTF-16文本前,首先要弄清楚每一個編碼單元的字節序。例如收到 一個「奎」的Unicode編碼是594E,「乙」的Unicode編碼是4E59。若是咱們收到UTF-16字節流「594E」,那麼這是「奎」仍是 「乙」?.net

Unicode規範中推薦的標記字節順序的方法是BOM。BOM不是「Bill Of Material」的BOM表,而是Byte Order Mark。BOM是一個有點小聰明的想法:excel

在 UCS編碼中有一個叫作"ZERO WIDTH NO-BREAK SPACE"的字符,它的編碼是FEFF。而FFFE在UCS中是不存在的字符,因此不該該出如今實際傳輸中。UCS規範建議咱們在傳輸字節流前,先傳輸 字符"ZERO WIDTH NO-BREAK SPACE"。code

這樣若是接收者收到FEFF,就代表這個字節流是Big-Endian的;若是收到FFFE,就代表這個字節流是Little-Endian的。所以字符"ZERO WIDTH NO-BREAK SPACE"又被稱做BOM。blog

UTF- 8不須要BOM來代表字節順序,但能夠用BOM來代表編碼方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8編碼是EF BB BF(讀者能夠用咱們前面介紹的編碼方法驗證一下)。因此若是接收者收到以EF BB BF開頭的字節流,就知道這是UTF-8編碼了。

Windows就是使用BOM來標記文本文件的編碼方式的。

google發現問題源頭(仍是GOOGLE給力!!)

http://phpexcel.codeplex.com/discussions/237813

上文解決方法有誤。按照上述方法,在緩衝區處理BOM頭。問題沒有解決。經過ob_get_contents導出到文件查看,並無發現BOM頭的存在,BOM頭是在發送之後某個階段添加的。

無奈,批量修改全部源碼的BOM頭。問題完全解決。

回過頭一想,爲何添加了D('someAction')行代碼就出問題。可能由於該代碼自動連接了某些代碼文件,而這些文件都是帶有BOM開頭的utf-8文件。

附批量修改全部文件BOM頭的腳本:http://blog.csdn.net/lgg201/archive/2010/09/02/5860125.aspx

 

 

OK, I finally found a work arround. I put the following 2 lines of code before redirecting output to the client browser and it looks that it fixed the problem. Probably that strange characters were sent to the browser. So, calling ob_end_clean() seams to clean the output buffer before sending the excel document. ob_start() is also important to reopen the output buffer.

...

ob_end_clean(); // Added by me
ob_start(); // Added by me

// Redirect output to a clients web browser (Excel5) header('Content-Type: application/vnd.ms-excel'); ...

相關文章
相關標籤/搜索