2013年8月27日火曜日

php fputcsvを使わないでCSVファイルをダウンロードする

自サーバでDBのでーたをCSVファイルにしてダウンロードするロジックを検証していました。

(WordPressのプラグインを利用しています。)

(トラブル現象)
1、3件出なければいけないところ、2件しかCSVファイルに出てこない。
2、CSVファイルの見出しのひとます目に「・ソ」「x'EFBBBF'」が入り、文字化けした。

(原因)
1、については、レコードは三件きちんとデータとして吐き出されている。しかし、一番最後のレコードの一番最後のアイテムのデータが壊れていることが分かりました。

2、については、ファイルの先頭三バイトに「x'EFBBBF'」が挿入されていてこれがもとで最初のアイテムが文字化けしてしまっていることが分かりました。この三バイトがどこでセットされているかは、推測ですが、アウトプット・バッファーにデータをfputcsvしたときでは?と思います。

※この三バイト「x'EFBBBF'」は後にBOM付きUTF-8ファイルと呼ばれる品物であることが判明。


(対応)

1、CSVの項目の区切りを「”」、各項目ごとの区切りを「,」にして変換しているロジックを
mb_str_replace()を使ってコンバートする。
※mb_str_replace()は、予め、ダウンロードして、稼動DIRに設置しておく。

2、アウトプットバッファーのクリーニングを、ob_end_clean()を使ってお掃除した上で
fwrite()を使ってファイルプットする。

3、CSVデータ1レコードの終わりに改行コード\r\nをつける。

4、fputcsvとmb_str_replaceを参考に問題プログラムを修正する。

修正コードCSVレコードGenerate部分

function prv_fputcsv($fp, $data, $encoding="") {
 require_once 'mb_str_replace.php';

 $csva = '';
 foreach ($data as $col) {
  $col = mb_str_replace('"', '""', $col, $encoding);
  $csva .= "\"$col\",";
 }
 fwrite($fp, "$csva\r\n");
} 

ファイルダウンロード部分

     
$file_size = @filesize($full_file_name);
     ob_end_clean();
     ini_set("zlib.output_compression","0");
     header("Pragma: public");
     header("Expires: 0");
     header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
     header("Cache-Control: public");
     header("Content-Type: text/csv");
     header("Content-Disposition: attachment; filename=".$file_name);
     header("Content-Length: ".$file_size);
     @readfile($full_file_name);
     @unlink($full_file_name);

このように、二箇所の修正を行いました。

(結果)

前出のトラブル現象はずべて解消しました。

めでたし、めでたし。

※ソースの部分に、SyntaxHhgilighterを当ブロガーに導入しました。
 導入方法は追ってアップできればと思っています。

0 件のコメント:

コメントを投稿