7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Edge,IE11だけFileListにevent.dataTransfer.filesが入らない

Posted at

経緯

ドラッグ&ドロップ式 ファイルアップロード画面のIE対応でハマった話
モダンブラウザではきちんと動くのに、edgeとIE11だけドロップしても動かない。

// input要素
const fileInput = document.getElementById("fileInput")
// ファイルをdropする要素
const dropTarget = document.getElementById("dropTarget")

function hoge(event) {
  event.preventDefault()
  event.stopPropagation()
  event.dataTransfer.dropEffect = 'copy'
}

function fuga(event) {
  event.stopPropagation()
  event.preventDefault()
  fileInput.files = event.dataTransfer.files; //今回問題の部分
}

dropTarget.addEventListener('dragover', e => {
  hoge(e)
})
dropTarget.addEventListener('drop', e => {
  fuga(e)
})

よくあるドラッグ&ドロップでフォーム実装する時の処理ですね。
<input type="file">のFileListオブジェクトに対して、
なぜかIE系だけevent.dataTransfer.filesが入らない。
これに結構ハマりました。

対応

何やらIEからは「厳密モードのFileListは読み取り専用なので代入できません」って怒られます。
babelが吐き出してくれるソースにはデフォルトでuse strictが付くので、取っちゃおうかと考えました。

.babelrc
{
  "sourceType": "script"
}

"sourceType": "script".babelrcに追加することで、
バベられた後のソースからuse strictを取っ払うことができます。

しかしこの対応でも動かない。

しかも"sourceType": "script"を指定すると
import/exportがつかえなくなります。(しんどい)
何よりuse strictを取るって対応そのものが単純に敗北感が強い。

解決

色々調べましたが、結局あまりスマートな解決の糸口が見つからず、
event.dataTransfer.files<input type="file">
FileListオブジェクトに突っ込まない方法で解決。


// input要素
const fileInput = document.getElementById("fileInput")
// 画像をdropする要素
const dropTarget = document.getElementById("dropTarget")

function piyo(data) {
  const formData = new FormData(document.getElementById("form"))
  formData.append('image', fileData[0])
  //APIコール用のロジック
}

function hoge(event) {
  event.preventDefault()
  event.stopPropagation()
  event.dataTransfer.dropEffect = 'copy'
}

function fuga(event) {
  event.stopPropagation()
  event.preventDefault()
  piyo(event.dataTransfer.files);
}

dropTarget.addEventListener('dragover', e => {
  hoge(e)
})
dropTarget.addEventListener('drop', e => {
  fuga(e)
})

event.dataTransfer.filesを引数で渡していって
formdataに突っ込んでAPIに投げてあげる形に。
formdataがFilelistオブジェクトしか受け付けない。
みたいになってたら詰んでました。

File()で新しくインスタンス生成する方向でも考えたものの、
第二引数に渡すBlob型のデータをdropで取得する方法がわからないのと、
普通にクリック処理でファイルを受け取る場合は
<input type="file">のデフォルトの挙動に頼っていたので断念。

これ上手なやり方ご存知の方はぜひ教えてください。

7
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?