web-dev-qa-db-ja.com

ページにファイルをドロップするときにファイル入力値を設定するにはどうすればよいですか?

フォームで送信するファイルを選択し、同じことを行うためにファイルをドロップすることができるコントロールを作成しようとしています。私はこのようなものがあり、画像の場合はファイルのプレビューも表示します:

<div class="preview-image-container">

  <input type="file" name="File" id="File" accept="image/*" 
         class="image-url form-control" style="display:none;" />

  <div class="preview-image-dummy"></div><img class="preview-image-url" />
  <div class="preview-image-instruction">
    <div class="preview-image-btn-browse btn btn-primary">Select file</div>
    <p>or drop it here.</p>
  </div>

</div>

MCVEのフィドル

ユーザーはpreview-image-containerにファイルをドロップします。ファイルはAJAXでは送信されません。ユーザーはより多くのデータを含むフォームを送信する必要があります。

セキュリティ上の理由から、JavaScriptを使用して入力ファイルの値を変更することはできません。ただし、デフォルトの入力ファイルはドロップ可能をサポートしており、ファイルをフォームにドロップして選択できるウェブサイトがたくさんあることを知っているので、それを行う方法があると思います。

MCVEからわかるように、追加のライブラリなしでjQueryまたはpure JavaScriptを使用することにのみ興味があります。

dropzone.jsを使用することもできますが、それは私の要件に適合せず、外観をカスタマイズするにはかなりの時間を必要とします。さらに、dropzone.jsには、ASP.NETアプリケーションでは満たすことができない特定の構成要件があります。


同様の質問がありますが、適切な答えはありません。
HTMLのフォームの入力ファイルにファイルオブジェクトを設定する方法

また、 アップロード前にドロップ画像入力ファイルとプレビューをドラッグする と似ていないため、すでにドラッグドロップとプレビューのアクションを達成しています。 私の質問は、親コンテナにファイルをドロップするときに空のファイル入力があるという問題に固有です。

49
Tristan

免責事項:2017年12月現在および最新のブラウザのみに修正


TL; DR:はい、できます!

* dataTransferまたはFileListオブジェクトがある場合

以前、プログラムによるファイルinput[type=file]フィールドの変更は、最新のブラウザで修正されたレガシーセキュリティの脆弱性により無効にされていました。

最近の主要なブラウザ(Firefox)により、入力ファイルフィールドにファイルを設定できるようになりました。 W3C testing によると、Google Chromeですでにこれを行うことができるようです!

MDNから引用された関連するスクリーンショットとテキスト:

enter image description here

最新のすべてのブラウザでHTMLInputElement.filesの値を取得するだけでなく、setを実行できます。
ソースとブラウザの互換性、 MDNを参照

Firefox バグ修正議論 スレッドにはこれがあります demoあなたはテストできます編集する場合はソース 。このリンクが切れた場合の将来の参照のために、以下の実行可能なスニペットとしても含めます。

let target = document.documentElement;
let body = document.body;
let fileInput = document.querySelector('input');

target.addEventListener('dragover', (e) => {
  e.preventDefault();
  body.classList.add('dragging');
});

target.addEventListener('dragleave', () => {
  body.classList.remove('dragging');
});

target.addEventListener('drop', (e) => {
  e.preventDefault();
  body.classList.remove('dragging');
  
  fileInput.files = e.dataTransfer.files;
});
body {
  font-family: Roboto, sans-serif;
}

body.dragging::before {
  content: "Drop the file(s) anywhere on this page";
  position: fixed;
  left: 0; width: 100%;
  top: 0; height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 1.5em;
  background-color: rgba(255, 255, 0, .3);
  pointer-events: none;
}

button, input {
  font-family: inherit;
}

a {
  color: blue;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
      <link href="https://fonts.googleapis.com/css?family=Roboto:400,400i,700" rel="stylesheet"> 

  <title>JS Bin</title>
</head>
<body>
  
  <h1>Drag and drop files into file input</h1>
  
  <p><small>Supported in <a href="https://github.com/whatwg/html/issues/2861">WebKit and Blink</a>. To test, drag and drop one or more files from your operating system onto this page.</small></p>
  
  <p>
    <input type="file">
  </p>

</body>
</html>

重要な注意:

入力ファイル要素に設定できる既存のFileList OR dataTransferオブジェクトがある場合にのみこれを行うことができます(setterメソッドはプレーンテキスト文字列を受け入れないため) )。

詳細については、こちらのKaiidoの回答を参照してください。 ファイルがFormDataオブジェクトにも反映されるFileListオブジェクトでFileオブジェクトとlengthプロパティを設定する方法?


元の質問に答えるには、次のように簡単にする必要があります。

document.querySelector('.preview-image-instruction')
    .addEventListener('drop', (ev) => {
        ev.preventDefault();
        document.querySelector('.image-url').files = ev.dataTransfer.files;
    });
65
Samuel Liew