こんにちは、いつもお世話になっております。
CSVのインポートとエクスポート機能を作っています。
FILE APIを使ってローカルからファイル中身を読み取ってDBに入れるインポートと、DBにあるデータをCSVファイルに吐き出すエクスポートを実装しようとしてます。インポートはなんとか作り、今はエクスポートの方を使っています。
やりたいのは、Cakehphp3のコントローラーからDBの情報を配列で作り、Ajaxで渡してFILE APIを用いてローカルにダウンロードさせることです。
https://qiita.com/wadahiro/items/eb50ac6bbe2e18cf8813
このリンク先のサンプル2番目の感じです。サンプルのテストは上手く行きましたので、以下のように書いてみましたが、ファイルが生成されず、そのまま最後まで走ってしまいます。
デバッグしてみたら、blobオブジェクトが怪しいかな、と思います。ファイル名やJSON,配列のデータは思い通りに取れていますが、なぜかmsSaveBlob, msSaveOrOpenBlob, else(chrome等用)までひっかからずパースしてしまいます。
どこがおかしいのか、怪しいところや何かヒントがありましたら教えてください。
ソースコードとDebugした画面を添付します。宜しくお願い致します。
コントローラー側では、DBからデータを出してそれをSerializeするだけです。
public function export() { if($this->request->is('ajax')) { $customer_idx = $this->Auth->user('customer_idx'); $sections = $this->Section->find()->where(['customer_idx' => $customer_idx]) ->select(['section_idx','year','customer_idx','section_code','section_name','section_short','memo','is_used','deleter','deleted']) ->epilog('FOR UPDATE') ->toArray(); if(!empty($sections)) { // success $results = $sections; $this->Flash->success(__('データベースからエクスポートに成功しました。')); } else { //failed $results = null; throw new exception($e); $this->log($e); $this->Flash->error(__('エクスポート失敗[DBデータエラー](E30005)')); } $this->set('result', $results); $this->set('_serialize', ['result']); } }
クライアントの方は、ファイル名を入力してもらい、そのファイル名でCSVファイルを生成したいです。<a>タグのdownload
プロパティ使うということでしたので、CSV出力ボタンを押すと、ファイル名を.arrで追加する形にしました。
HTML
1<div class="form-group"> 2 <div class="col-lg-12"> 3 <?= $this->Form->control('filename', ['class' => 'form-control','label' => 'CSVファイル名', 'type' => 'text', 'required' => 'required', 'id'=>'filename']); ?> 4 </div> 5</div> 6 7 <div class="form-group" align="center"> 8 <?= $this->Html->link( 9 '戻る', $referer, 10 ['class' => 'btn btn-success btn-sm', 'type' => 'button'] 11 ); ?> 12 13 <a id="download" href="#"><button type="button" class="btn btn-primary btn-sm">CSV出力</button></a>
スクリプトの方はこんな感じです。
<script type='text/javascript'> $('#download').on('click', function(e){ // ファイル名をAタグのDownload属性で追加 e.preventDefault(); var filename = $('#filename').val() + ".csv"; $('#download').attr('download',filename); if(window.File && window.FileReader && window.FileList && window.Blob) { if($('#filename').val()=='') { alert('CSVファイル名は必ず入力してください。'); return false; } if(!confirm('CSVファイルにマスタ情報の出力を行います。本当によろしいですか?')) { alert('CSVファイル出力をキャンセルしました。'); return false; } else { $.getJSON('../section/export', null, function(data,status){ // phpから連想配列をとってくる if(status) { var contents = []; var bom = new Uint8Array([0xEF, 0xBB, 0xBF]); // UTF-8のBOMコード for(var key in data.result) { contents[key] = []; //配列の要素数を指定する contents[key] = Object.values(data.result[key]); // 連想配列を配列にする。 } 'use strict'; var csvContents = CSV.stringify(contents); // CSV化する。 // データをファイルとして作る var blob = new Blob([bom,csvContents], { type : 'text/csv;charset=utf-8;' }); if (window.navigator.msSaveBlob) { window.navigator.msSaveBlob(blob, filename); window.navigator.msSaveOrOpenBlob(blob, filename); } else { $('#download').attr('href',(window.URL || window.webkitURL).createObjectURL(blob, {type: "application/octet-stream"})); } } else { alert('DBエラー'); return false; } })
回答2件
あなたの回答
tips
プレビュー