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

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

ただいまの
回答率

90.33%

javascript:アップロード前のサムネイル表示をした後、任意の画像を削除したいです。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 8,854

blueBird

score 23

【やりたいこと】
PHP で複数あげられる画像アップローダーを作っています。
サブミットボタンを押下しformタグのactionが実行される前にサムネイルを表示します。
(ここまではできている)
たとえば、A,B,Cの画像を選択しサムネイルを表示します。そこで削除ボタンなどを設けてBだけを削除して、アップロードをするのをAとCだけにするといった内容です。

【現状と問題】
下記のソースの通り、削除ボタンを押すと
 $("input[type='file']").val(null);により全部消えてしまいますがこれを上手く任意の画像を削除するソースの記述の仕方、考えが浮かびません。どうしたら良いでしょうか。

javascript初心者です。お力を貸してください。

<form action="upload" method="post" enctype="multipart/form-data">
     <input id="files" type="file" name="upfile[]" size="30" multiple accept="image/jpeg," />
    <input type="submit"value="アップロード" />
</form>
<div id="file_list"></div>

<script>
    $(function() {
       var init = function() {
          // 選択後イベント
          $('input[name="upfile[]"]').change(function(evt) {
               $('div#file_list').text('');

               jQuery.each(evt.target.files, function(i) {
                    // サムネイル画像生成
                     var reader = new FileReader();
                      reader.readAsDataURL($(this)[0]);
                   // ファイル名表示

                      reader.onloadend=function(i){
                       $('div#file_list')
                       .append($('<img width="150px" height="100px" style="margin: 2px"/>').
attr('src', this.result),file_name+'<button onClick ="deleteThumbnail()">削除');
                      };
                     var file_name = ($(this)[0].name);


                     var files = document.getElementById("files").files[i];
                     console.log(files);

               });
           });
        }
       init();
     });

        function deleteThumbnail(){
            //サムネイル非表示
            $('div#file_list').remove();

            // input[]に上がったのを削除
            $("input[type='file']").val(null);
        }

</script>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

input[type="file"]の値の変更はセキュリティ上の問題とかでnullにする以外は認められていなかったかと思います。
つまり1つのinput[type="file"]で複数画像を選択させる場合、ファイル選択無しにする以外はjsで操作することができません。特定の1つを削除ができない訳です。
ですので、
1. 複数選択ではなく、1inputタグ1ファイルとし、画像選択時に新しいinput[type="file"]を作成し、画像削除時に該当するinput[type="file"]を削除させるのが良いかと思います。
あるいは、
2. 複数選択のままにしておき、アップロードするファイルのIDなどをリストに保持させて、画像削除時にリストから削除しフォームデータ送信時にそのリストを元に対象外のファイルを弾いてajaxで送信するとかでしょうか。

 1. 新しいinputタグを追加するパターン

<form action="upload" method="post" enctype="multipart/form-data">
  <ul id="file_list">
    <li class="js-file">
      <input class="js-inputFile" type="file" name="upfile[]" size="30" accept="image/jpeg" />
    </li>
  </ul>
  <input id="submitBtn" type="submit" value="アップロード" />
</form>
$(function() {
  var init = function() {
    // idはhtmlに1つなので $(#id名) とした方が高速
    var $fileList = $('#file_list');

    $fileList
    // ファイル削除イベント
    .on('click.deleteFile', '.js-deleteBtn', function(evt) {
      var $li = $(this).closest('.js-file');
      // input[type="file"]が1つ以上の場合は該当のinpuタグを削除する
      if($fileList.find('.js-file').length > 1) {
        $li.remove();
      } else {
        $li.find('.js-thumb').remove();
      }
      return false;
    })
    // ファイル選択時のイベント
    .on('change.inputFile', '.js-inputFile', function(evt) {
      var $input = $(this),
          fileID = $input.data('fid'),
          $li = $input.closest('.js-file'),
          $newLi;

      if(evt.target.files.length) {
        $newLi = $li.clone();
        $newLi.find('.js-inputFile').val(null);
        // 新しくinputタグを追加する
        $fileList.append($newLi);

        $.each(evt.target.files, function(i, elm) {
          var file = this,
              fileName = file.name,
              reader;

          // サムネイル画像生成
          reader = new FileReader();
          reader.readAsDataURL(file);

          // サムネイルを表示させる処理
          reader.onloadend = function(evt) {
            var fileReader = this;
            if(fileReader.result) {
              var thumb = '<div class="js-thumb"><img src="' + fileReader.result + '" width="150px" height="150px" style="max-width:100%;height:auto;">' + fileName + '<button class="js-deleteBtn">削除</button></div>';
              $li.append(thumb);
            }
            return this;
          };
        });
        $input.hide();
      } else {
        // ファイルが選択がキャンセルされた時 既にサムネイルが表示されてるなら削除する
        $li.find('.js-deleteBtn').trigger('click');
      }
      return this;
    });
  };
  init();
});

 2. フォームデータ送信時に対象外のファイルを弾くパターン

<form id="myForm" action="upload" method="post" enctype="multipart/form-data">
  <input id="js-inputFile" type="file" name="upfile[]" size="30" multiple accept="image/jpeg" />
  <input id="submitBtn" type="button" value="アップロード" />
</form>
<ul id="file_list"></ul>
$(function() {
var init = function() {
    var $form = $('#myForm'),
        $fileList = $('#file_list'),
        filesObj;

    // サムネイル削除時
    $fileList.on('click.deleteFile', '.js-deleteBtn', function(evt) {
      var $li = $(this).closest('.js-thumb'),
          fileID = $li.data('img-id');
      $li.remove();
      // ファイルリストから削除
      delete filesObj[fileID];
      return false;
    });

    $form
    // ファイル選択時
    .on('change.selectFiles', '#js-inputFile', function(evt) {
      // ファイルリスト・ファイルリストを初期化
      $fileList.html('');
      filesObj = {};
      jQuery.each(evt.target.files, function(i, elm) {
        var file = this,
              fileName = file.name,
              fileIndex = i,
              reader;
        // ファイルリストに追加
        filesObj[i] = file.name;

        // サムネイル画像生成
        reader = new FileReader();
        reader.readAsDataURL(file);

        // サムネイルを表示させる処理
        reader.onloadend = function(evt) {
          var fileReader = this;
          if(fileReader.result) {
            var html = '<li class="js-thumb" data-img-id="' + fileIndex + '"><img src="' + fileReader.result + '" width="150px" height="150px" style="max-width:100%; height: auto;">' + fileName + '<button class="js-deleteBtn">削除</button></li>';
            $fileList.append(html);
          }
          return this;
        };
        return this;
      });
    })
    // フォーム送信時の処理
    .on('click.formSubmit', '#submitBtn', function(evt) {
      var formData = new FormData(),
          files = $('#js-inputFile').prop("files");

      for(var i=0, l=files.length; i<l; i+=1) {
        // 削除されていないファイルだけを送信するように整形
        if( filesObj[i] ) {
          formData.append("upfile[]", files[i]);
        }
      }
      // その他のデータもある場合は formData に追加する

      $.ajax({
        url: 'API_URL フォーム送信先のURL ',
        method: 'post',
        dataType: 'json',
        data: formData,
        processData: false,
        contentType: false,
      })
      .done(function( res ) {
        console.log('送信成功', res);
      })
      .fail(function(jqXHR, textStatus, errorThrown) {
        console.log('送信失敗', jqXHR, textStatus, errorThrown);
      });
      return false;
    });
  };
  init();
});
手前味噌で恐縮ですが、ファイルをAjaxで送信するのはコチラを参照下さい。
jQuery Ajaxでファイルを送りたい! - かもメモ
  ※ ちょっと古い記事なので今ならもっとモダンな方法があるかもしれませんが...

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

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