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

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

ただいまの
回答率

88.91%

jqueryのajax通信で送られてきたCSVをPHP側で見れない

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 234

zepp

score 19

前提・実現したいこと

input type=fileで選択したcsvをajaxでPHPに送り、PHPでそのcsvを非同期で処理したいと思っています。
しかし、その送られてきたファイルをPHPでfile_get_contents()しても返り値がnullになります。
現段階では、送られてきたCSVの中身を文字列ないし、fgetcsv()で扱えるようになりたいです。
submitは使えない前提です。

発生している問題

PHP側のファイルの扱い方が間違っているのか、JS側のajax通信の仕方が間違っているのか、ファイルの中身を取得出来ません。
現在、PHP側を試しに下記のようなコードにしています。
js側でconsole.log()にてこのfile_get_contents($fp)の返り値を見るとnullになっておりました。

$tmp_name = $_FILES['file']['tmp_name'];
$fp = fopen($tmp_name, 'rb');
header('Content-type: application/json');
echo file_get_contents($fp);

js->phpのリクエスト自体は200で成功しています。
下記が送信したフォームデータをChromeの開発者モードで見たものです。

file: (binary)
flag: csvUpload
pid: 1

該当のソースコード

<div class="form-group">
    <input type="file" class="form-control-file" id="csvFile" accept="text/csv">
</div>
<div class="form-group">
    <button type="button" class="btn btn-success" id="uploadBtn">アップロード</button>
</div>
$(document).on('click','#uploadBtn',function(){
    var fd = new FormData();
    fd.append("file", $("#csvFile").prop("files")[0]);
    fd.append("flag", "csvUpload");
    $.ajax({
        url : phpのurl,
        type: "POST",
        dataType: "json",
        data: fd,
        processData: false,
        contentType: false
    })
    .done(function(data){
        console.log(data);
    })
    .fail(function(jqXHR){ 
        console.log(jqXHR);
    });
})
$res = array("status"=>"error","data"=>"");
if($_REQUEST["flag"] == 'csvUpload') {
    $tmp_name = $_FILES['file']['tmp_name'];
    $fp = fopen($tmp_name, 'rb');

    $res["data"]["filecontents"] = file_get_contents($fp);
    $res["data"]["filepath"] = $tmp_name;

    // 処理中略, ファイル処理が成功すれば$res["status"] = "success"

    header('Content-type: application/json');
    echo json_encode($res);
    exit();
}

補足情報

php v7.0.31
jQuery v2.1.4
使用想定ブラウザ Chromeのみ

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+3

まずは普通にpostして読めるかどうかを検証するのが先。
ファイルポインタで掴んでるのに、file_get_contentしているのはなぜでしょう?
csvファイルを読んでいるのにjsonを返そうとしているのもおかしいです 

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/17 15:51

    PHPが受け取るのはCSVですけど、返すのは最終的にCSVじゃないので大丈夫ですー

    キャンセル

  • 2020/07/17 16:01

    つまりCSVをそのまま出力しようとしている命題が間違えているということですね?
    CSVを配列やオブジェクトに展開して、JSONエンコードして出力してください

    キャンセル

  • 2020/07/20 10:56

    > 送られてきたCSVの中身を文字列ないし、fgetcsv()で扱えるようになりたいです。
    命題これっすねー。
    一応本文には書いてたんですが、タイトルと齟齬がありましたね。
    修正してみました。
    勘違いさせてしまって申し訳ありません。

    キャンセル

0

echo json_encode($res);
exit();


の部分を

return json_encode($res);


としてはいかがでしょうか?

理由は以下の通りです。
jsファイル内の

.done(function(data){
        console.log(data);
    })


dataajaxのポスト送信の返り値を表しています。
一方PHPファイルで使用されているechoreturnとは違い返り値を返すものではない(返り値はnullとなる)し、exit()を使用すると返り値自体がnullととなります。
よって、PHP側の返り値の値を返すreturnをPHPファイル内で使用することでjsファイルのdatanullにならないと思うからです。

参照
PHPドキュメント echo
PHPドキュメント exit

追記
自分が作成したこの回答はPHPのheader()の用途を完全に勘違いしたものでした。なのでこの回答は参考にしないでください。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

PHP は知らない自分がレスするのもなんですが・・・

CSV ファイルは期待通りに送信されてますか?

質問のコードに、

fd.append("file", $("#csvFile").prop("files")[0]);

とあって、これが CVS ファイルを append したつもりですか? ここが変だと思います。

質問に <input type="file" ... というコードがありますが、ユーザーがそれで送信するファイルを選択し、<button type="button" ... クリックで jQuery ajax を使ってアップロードするのですよね?

であれば、var fd = new FormData(document.querySelector("form")); で送信するファイルが含まれた FormData オブジェクトを取得できるので、それを jQuery ajax の data に設定すれば multipart/form-data 形式で送信されるはずです。

もちろん、form 要素の enctype 属性に "multipart/form-data" が設定されていなければなりませんが。

Fiddler を使って期待通り送信できているか調べてみてはいかがですか?

そのあたりの話は、別のスレッドの私の回答 https://teratail.com/questions/277964#reply-395868 に書きましたので見てください。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/17 15:52

    > これが CVS ファイルを append したつもりですか? ここが変だと思います。
    CSVファイルは期待通りにappendされてました

    キャンセル

  • 2020/07/17 17:43

    それは失礼しました。

    キャンセル

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

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

関連した質問

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