質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.75%

  • PHP

    19168questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • JavaScript

    15261questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • HTML

    8293questions

    HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

  • jQuery

    6311questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • CakePHP

    2214questions

    CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

ControllerでCSVを読み込んだ後に確認ダイアログを表示したい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 172

taiyo-2017

score 11

お世話になります。
作りたい処理としては、

  1. web画面上でボタンをクリック
  2. ファイル選択ダイアログが表示される
  3. ファイルを選択したらCSVファイルを読み込む
  4. Controllerにてファイル名が合っているか、項目数が合っているか、項目名は合っているかをチェック
  5. 内容が正しい場合は「登録しますか?」といったダイアログを表示
  6. 「はい」の場合にCSVのデータを登録する

といったことになります。

submitをすることで
1~4までのCSVの内容を確認することはできたのですが、
submitしてしまった後では確認ダイアログを表示することができないのでは?と思い
実装に悩んでいるところです。

アドバイス等をいただければと思います。

現状の、CSVの内容を取得するPGを記載しておきます。

ctp

<?=$this->Form->create(null, ['type' => 'file','url' => ['action' => 'check_csv'],'onsubmit' => 'return false;', 'name' =>'myform' ])?>
  <form enctype="multipart/form-data" method="post">
  <input id="filReadDep" name="filReadDep" type="file" value="" onChange="chgReadDep()"/>
  <button onClick="imgReadDep()"><?= $this->Html->image("buttons.png")?></button>
  </form>
<?= $this->Form->end(); ?>

javascript

function imgReadDep() {
  document.getElementById("filReadDep").value = "";
  document.getElementById("filReadDep").click();
}

function chgReadDep() {
  document.myform.submit();
}

Controller

//ファイルパスチェック
    if (empty($this->request->data['filReadDep']['tmp_name'])) {
      $this->Flash->error(__('select {0}', __('csv')));
      \Cake\Log\Log::info(__('select {0}', __('csv')) . "\n", 'csv_import');
      \Cake\Log\Log::info(__('failed_import'), 'csv_import');

      return;
    }

    //拡張子チェック
    $fileNm = $this->request->data['filReadDep']['name'];
    $tmpAry = explode('.', $fileNm);
    $extension = $tmpAry[count($tmpAry) - 1];

    if ($extension != 'csv') {
      $this->Flash->error(__('different {0}', __('File_Format')));
      \Cake\Log\Log::info(__('different {0}', __('File_Format')) . "\n", 'csv_import');
      \Cake\Log\Log::info(__('failed_import'), 'csv_import');

      return;
    }

    //CSVファイルを配列に保存
    $tmp = fopen($this->request->data['filReadDep']['tmp_name'], "r");
    while ($csv[] = fgetcsv($tmp, "1024")) {
    }
    //配列 $csv の文字コードをSJIS-winからUTF-8に変換
    mb_convert_variables("UTF-8", "SJIS-win", $csv);
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

二つの手が考えられるかなと思います。

A. サーバーに一時ファイルとして保存する。
「はい」が選ばれたら一時ファイルを本番に保存します。

B. 一度AjaxでFormData()を使って送信してしまう。
再送信することになるので、ファイルサイズが大きいと不利かも。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/15 17:20

    回答ありがとうございます。
    ファイルサイズが大きくない想定のため、
    「B. 一度AjaxでFormData()を使って送信」を行いたいと考えています。
    ですが、実装の方法が分からず…といった状態です。
    どのような実装方法がありますでしょうか?

    キャンセル

  • 2018/01/15 17:25

    この辺参考になりますか?
    https://qiita.com/BRS_matsuoka/items/ba79a2f500a10ddc0923
    なお、この方法をとると再送信時にファイルの内容が変わっている可能性もあるため、もう一度チェックする処理を通す必要があります。

    キャンセル

  • 2018/01/15 19:55 編集

    参考のURLありがとうございます!
    ajaxは動作しているようなのですが、formの内容をうまくpostできていないのか、
    postした内容をController側で「$this->request->getData();」を表示したところ
    「Array」と表示されるようになってしまいました。
    解決方法などはありますでしょうか?
    ctpは変更せず、jsの「document.myform.submit();」を下記のように変更しています。
    --------------------------------------------
    var fd = new FormData();
    if ($("input[name='filReadDep']").val() !== '') {
    fd.append("file", $("input[name='filReadDep']").prop("files")[0]);
    }
    fd.append("dir", $("#hoge").val());
    var postData = {
    type : "POST",
    url : $('#check-csv-url').text(),
    data : fd,
    processData : false,
    contentType : false
    };
    $.ajax(postData).done(function(data) {
    // 処理
    });

    キャンセル

  • 2018/01/15 21:45

    #hogeってありました? その行は不要じゃないですかね?

    キャンセル

  • 2018/01/16 08:44 編集

    ご指摘ありがとうございます。
    ctpファイルの変更はないと記載しましたが、紹介していただいたサイトを参考に
    <input id="hoge" type="hidden" value="hoge">
    を追加しているため、文法エラーにはなっていません。失礼しました。
    実際に作成するPGもCSVとパラメータを渡したいと考えているため
    このまま残せるなら残しておきたい、と考えています。
    少し見にくいですが、以下がctpのform前後の内容となります。
    formを使用しているのはこの部分だけになります。
    --------------------------------------------
    <?=$this->Form->create(null, ['type' => 'file','url' => ['action' => 'check_csv'],'onsubmit' => 'return false;', 'name' =>'myform', 'id' =>'myform' ])?>
    <form enctype="multipart/form-data" method="post">
    <input id="filReadDep" name="filReadDep" type="file" value="" onChange="chgReadDep()" class="DisplayNone"/>
    <button class="" onClick="imgReadDep()"><?= $this->Html->image("buttons.png")?></button>
    </form>
    <?= $this->Form->end(); ?>
    <input id="hoge" type="hidden" value="hoge">

    キャンセル

  • 2018/01/16 09:51

    そういえば$this->Form->createが<form>タグを生成しますよね? 二重に出力されていないか動かしたときのHTMLを確認してみてください。

    キャンセル

  • 2018/01/16 13:24

    formタグは1つのみ出力されているようでしたが、ヘルパーで作成しているformに統一するようにしました。
    その他も検証を行っていたところ、CSVファイルの内容とパラメータを取得することができました!
    ありがとうございます!
    ですが処理を行った後、ajaxの.done()での処理にControllerで作成した値を使用したいのですが、値の渡し方が分かりません…。
    現在はcontroller側でecho json_encode($result);をしており、jsでは.done(result){/*処理*/}といった記述をしているのですが、思ったように値が取得できない状態です。
    controllerからajaxに配列を渡したいのですがどのような記述ができますでしょうか?

    キャンセル

  • 2018/01/16 13:32

    json形式で受け取るときはdataTypeに'json'を指定します。
    http://api.jquery.com/jQuery.ajax/
    https://itsakura.com/jquery-ajax

    キャンセル

  • 2018/01/16 14:32

    json形式で取得できました!
    ajaxで処理を行い、処理の結果によって分岐させて、確認ダイアログを表示することができました!
    最後に行いたい処理の登録についてはまだ着手できていませんが、
    タイトルの内容については達成できたため、ここで質問を切らせていただこうと思います。
    アドバイスありがとうございました!

    キャンセル

0

自己解決ではありませんが、参考のために参考PGを記載させていただきます。

ctp

<?=$this->Form->create(null, ['type' => 'file','url' => ['action' => 'check_csv'],'onsubmit' => 'return false;', 'name' =>'myform', 'id' =>'myform', 'enctype' => 'multipart/form-data' ])?>
  <input id="filReadDep" name="filReadDep" type="file" value="" onChange="chgReadDep()" class="DisplayNone"/>
  <button class="btnMa mt5px" onClick="imgReadDep()"><?= $this->Html->image("buttons_ma1.png", $ma1_options)?></button>
<?= $this->Form->end(); ?>
<input id="hoge" type="hidden" value="hoge">

js

/* ボタンをクリックした際にファイル選択ダイアログを表示 */
function imgReadDep() {
  document.getElementById("filReadDep").value = "";
  document.getElementById("filReadDep").click();
}

/* ファイルを選択した際にファイルを読み込み */
function chgReadDep() {
  var fd = new FormData();
  if ($("input[name='filReadDep']").val() !== '') {
    fd.append("file", $("input[name='filReadDep']").prop("files")[0]);  // 選択したファイル
  }
  fd.append("dir", $("#hoge").val());  // パラメータを追加
  // for(item of fd) console.log(item);  // データ内容を確認できる
  var postData = {
    type : "POST",
    url : $('#test').text(),  // action(今回は「check_csv」)が格納されている
    data : fd,
    dataType : 'json',
    processData : false,
    contentType : false
  };
  $.ajax(postData).done(function(data) {
    if (data.check) {
      if (data.result) {
        // 処理
      }
      if (!window.confirm("ファイルの内容を登録します。よろしいですか?")) {
        alert("登録がキャンセルされました。");
        return;
      }
      alert("登録しました。");
    } else {
      alert(data.message); // エラーメッセージ
      return;
    }
  }).fail(function(data) {
    alert("読み込み処理に失敗しました。");
  }).always(function(data) {
  });
}

Controller

public function checkCsv(...$path)
  {
    $select_table = $_POST["dir"];

    $result = [
      "check" => false,
      "result" => false,
      "message" => ""
    ];
    // ファイルパスチェック
    if (empty($_FILES["file"]["tmp_name"])) {
      $result["message"] = "ファイルが読み込めませんでした。";
      $this->autoRender = false;
      echo json_encode($result);
    }

    // 拡張子チェック
    $fileNm = $_FILES["file"]["name"];
    $tmpAry = explode('.', $fileNm);
    $extension = $tmpAry[count($tmpAry) - 1];

    if ($extension != 'csv') {
      $result["message"] = "拡張子がCSVではありません。";
      $this->autoRender = false;
      echo json_encode($result);
    }

    // CSVファイルを配列に保存
    $tmp = fopen($_FILES["file"]["tmp_name"], "r");
    while ($csv[] = fgetcsv($tmp, "1024")) {}
    // 配列 $csv の文字コードをSJIS-winからUTF-8に変換
    mb_convert_variables("UTF-8", "SJIS-win", $csv);

    // csv内容チェック
    // csvの1列目1項目目を判断
    if($csv[0][0] == "aaa"){
      // 処理
    }
    // csvの1列目2項目目を判断
    if($csv[0][1] == "bbb"){
      // 処理
    }    
    // その他の処理

    $this->autoRender = false;
    echo  json_encode($result);
  }

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.75%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    19168questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • JavaScript

    15261questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • HTML

    8293questions

    HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

  • jQuery

    6311questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • CakePHP

    2214questions

    CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。