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

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

ただいまの
回答率

87.37%

jQueryでFormData()を送っても、PHPでinputの値が受け取れません

解決済

回答 2

投稿 編集

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

score 3

実現したいこと

こちらの<form>で画像が選択できる機能がjQueryであるのですが、その選択された画像(inputimg_file)を送り、PHPで受け取りたいです。

<form class="testform">
    <ul id="file_list">
        <li class="each_file">
            <input type="file" class="input_file" name="img_file" value="" accept="image/*">
        </li>
    </ul>
    <input type="submit" id="submit_btn" value="画像アップロード">
</form>    

発生している問題

$_FILES['img_file']がPHPで受け取れません。

そのことは次のPHPにある通りecho json_encode($_FILES['img_file']);としてみたのですが、jQeuryでres=という風にコンソールに表示され、つまり何も返ってこなかったためにそう判断しました。

該当のソースコード

function my_ajax_upload_photos() {
    echo json_encode($_FILES['img_file']); 
    die();
}
$(document).on("click",".insert_testform", function(){
    insert_testform(); 
});

function insert_testform(){
    // フォームのHTMLを追加
    const testform = `
        <form class="testform A_UploadImg">
            <ul id="file_list">
                <li class="each_file">
                <input type="file" class="input_file" name="img_file" value="" accept="image/*">
                </li>
            </ul>
            <input type="submit" id="submit_btn" value="画像アップロード">
        </form>    
    `;
    $('body').prepend(testform);

    // 削除がクリックされた場合の処理
    let $fileList = $('#file_list');
    $fileList.on('click.deleteFile', '.delete_btn', function(){
        const $li = $(this).closest('.each_file');
        $li.remove();
        // inputタグ数が4つ未満になった場合に再度表示させる処理
        const $fileListLI = $('#file_list li input[name=img_file]');
        const inputFileNum = $fileListLI.length;
        // 最後のinputタグを表示する処理
        const lastInputFile = $fileListLI.eq(-1);
        if (inputFileNum < 4){
            $(lastInputFile).show();
        }
        return false;
    });

    // inputタグに画像が追加された場合の処理
    $fileList.on('change.inputFile', '.input_file', function(e){
        const $input = $(this);
        const $li    = $input.closest('.each_file');
        const $newLi = $li.clone();
        $fileList.append($newLi);

        // サムネイル画像を表示する処理
        const file = e.target.files[0];
        const fileName = file.name;

        // FileReaderオブジェクトの生成
        let reader = new FileReader();
        reader.readAsDataURL(file);

        reader.onloadend = function(){
            const fileReader = this;
            if(fileReader.result){
                const thumb = '<div class = "thumbnail"><img src = "' + fileReader.result + '" width = "150px" style = "max-width: 150px;">' + fileName + '<button class = "delete_btn">削除</button></div>';
                $li.append(thumb);
            }
            return this;
        };
        $input.hide();

        // 送信データ
        let fd = new FormData();
        fd.append( "file", $('input[name="img_file"]').prop("files")[0] );
        const ajax_action = "my_ajax_upload_photos";    
        fd.append( 'action', ajax_action ); // FormData を送る場合は送信内容をすべてそこに入れる (https://stackoverflow.com/questions/28002627/ajax-response-0-when-using-processdata-and-contenttype-input-file)

        $.ajax({
            url: 'http://...',
            type: 'POST',
            dataType: 'json',
            data: fd,
            // FormData を送る場合は processData と contentType が必要
            processData: false, 
            contentType: false
        })
        .done(function(res){
            c('res=', res);
        })
        .fail(function(XMLHttpRequest, textStatus, errorThrown) {
            ajax_fail_console(XMLHttpRequest, textStatus, errorThrown);    
        });
        //return this; // なんでここでretunしてるの?
    });
}


そしてAJAXの結果のresとして次がコンソールに表示されました。何も返ってこないようです。

res=

試したこと

上の$_FILES['img_file']でなく、そもそもの$_FILESを返してみました。

function my_ajax_upload_photos() {
    //echo json_encode($_FILES['img_file']); 
    echo json_encode($_FILES); // そもそもの`$_FILES`を返してみました。
    die();
}


そうして先ほどのjQueryの$.ajaxの結果のresは次のようになり、ここを見ると$_FILES['img_file']がないようだとわかりました。

res={
  file: {
    error: 0
    name: "gahag-011076.jpg"
    size: 22963
    tmp_name: "/tmp/phpZFj7sW"
    type: "image/jpeg"
  }
}


ということは、jQeuryのfd.append( "file", $('input[name="img_file"]').prop("files")[0] );が疑わしいと思い、これをコンソールに出してみました。

fd.append( "file", $('input[name="img_file"]').prop("files")[0] );
console.log( 'files=', $('input[name="img_file"]').prop("files")[0] );


そうして出た結果が次のものです。

files=File { 
  lastModified: 1591546547257,
  name: "gahag-011076.jpg",
  lastModified: 1591546547257,
  webkitRelativePath: "",
  size: 22963,
  type: "image/jpeg"
}


これをfd.appendとして送る先のjQueryは間違っているのでしょうか?
なにかのネット記事でこう指定していた(コンソールがこの値かはわかりませんがfd.append( "file", $('input[name="img_file"]').prop("files")[0] );のように指定していました)ので、何がいけないのかわからないのです。

さらに別の記事ではfd.append( "file", $('.testform').get(0) );という風な指定もあり試したのですが、その状態で同じようにecho json_encode($_FILES);を返すと、今度はjQeuryのresが次のように空の配列となりまして、何をしてもわからないでいます。

res=Array[]


夜分に長文で申し訳ございませんが、どなたかご助力頂けませんでしょうか。
宜しくお願い致します。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+3

appendするときにキー名を"file"にしているからresでfileになるのでは?
"img_file"にすればいいと思います。new FormData()と
appendでカスタマイズしたFormDataを送るときはinputのnameは無意味だったはず。

fd.append( "file", $('input[name="img_file"]').prop("files")[0] );
fd.append( "img_file", $('input[name="img_file"]').prop("files")[0] );

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/06/09 11:09

    >appendでカスタマイズしたFormDataを送るときはinputのnameは無意味だったはず
    大当たりです。一晩憔悴しました。どうもありがとうございます。

    キャンセル

+1

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/06/09 15:16

    formタグ自体不要ですよこのやり方だと。
    formオブジェクトからsubmitしていればformタグに要ると思いますが
    今は$.ajaxで直接postしているのでformタグに属性をどれだけ書いても関係ないです。
    むしろこの属性を書くとsubmitとクリックイベントの$.ajaxで2重にpostするようになると思います。
    ややこしいので<input type="submit" id="submit_btn" value="画像アップロード">
    を<button type="button" id="submit_btn">画像アップロード</button>みたい感じに変えたほうがいいと思います。

    キャンセル

  • 2020/06/09 16:27

    ご親切にどうもありがとうございます!助かります!確かにajaxのpostはformタグを参照するわけではないですもんね。仰る通りformタグはややこしいので外し、inputもbuttonに変えておきたいと思います。

    キャンセル

  • 2020/06/09 18:48

    確かにそうですね。
    あまりスポットでそこだけアップロードすることがないので気づきませんでした。
    (Ajaxアップロードするときはたいていtype=fileをhiddenにした別formに入れてました)

    キャンセル

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

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

関連した質問

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