フォルダーまたはファイルがdragover
またはdragenter
イベント。
ondrop
イベントには、MouseEvent
という名前のフィールドがあり、dataTransfer
という名前のフィールドがあり、ファイル(.files
)またはアイテム(.items
)がリストされています)、ブラウザに応じて、 Chrome と Firefox の両方で読むことができます。ただし、dragover
およびdragenter
イベントの場合、これらのフィールド(.files
および.items
)は空です。問題は、ドロップするのではなく、ドラッグするときにその情報が必要なことです。
注:ファイルとフォルダーの両方についてevent.dataTransfer.types[i] === "Files"
はtrue
。
次の回答 が私の質問に部分的に適合することがわかりました:
WebKit、つまりChromeでは、
getData
をいつ呼び出すことができるかについて非常に制限されています。dragstart
またはdragover
内では許可されていません。これは標準的なバグだと思います。
しかし、その答えは2012年からのものであり、トピックに関する実際の更新情報が見つかりません。したがって、これに関する更新情報を探しています。
TL; DRできない:(
この質問がまだ受け入れられていない理由を疑問に思っている場合は、read this meta question作成者OP、および 私の答え。
drag
/drop
ファイルこのトピックに関する多くのドキュメントでいくつかの調査を行い、さまざまなブラウザーで自分でテストしたので、ここでファイルのドラッグアンドドロップについて知っているすべてを要約することにしました。
ファイルをドラッグするとき、次のようないくつかのリスナーを使用できます。
dragenter
dragover
dragend
dragleave
これらがdrag
イベントであるとすると、event.dataTransfer
のfiles
プロパティはlength == 0
を持つか、空(null
)になります。
ドラッグイベントでファイルを読み取ることができると想像してください。ユーザーがサイトにファイルをアップロードしたくない場合でも、すべてを読み取ることができます。真面目には意味がありません。デスクトップから別のフォルダーにファイルをドラッグしているときに、誤ってそれをWebページにドラッグするとします。Webページがファイルを読み取り、サーバーに個人情報を保存します...thatセキュリティ上の大きな欠陥になります。
ただし、配列event.dataTransfer.types
を反復処理することで、ユーザーがファイルをドラッグしているかどうか(フォルダーによってファイルなので、フォルダーも意味するファイルごと)を検出できます。ドラッグイベントにファイルが含まれているかどうかを確認する関数を作成し、イベントハンドラーで呼び出すことができます。
例:
function containsFiles(event) {
if (event.dataTransfer.types) {
for (var i=0; i<event.dataTransfer.types.length; i++) {
if (event.dataTransfer.types[i] == "Files") {
return true;
}
}
}
return false;
}
function handleDragEnter(e) {
e.preventDefault();
if (containsFiles(e)) {
// The drag event contains files
// Do something
} else {
// The drag event doesn't contain files
// Do something else
}
}
ファイルをドロップ<div>
(またはドロップゾーンとして使用している要素)にドロップすると、イベントdrop
のリスナーを使用して、名前、サイズ、タイプと最終変更日。
ファイルがフォルダーかどうかを検出するには、次のようにします。
type == ""
があるかどうかを確認します。size%4096 == 0
。例:
function handleDrop(e) {
e.stopPropagation();
e.preventDefault();
var files = e.dataTransfer.files;
for (var i = 0, f; f = files[i]; i++) { // iterate in the files dropped
if (!f.type && f.size%4096 == 0) {
// The file is a folder
// Do something
} else {
// The file is not a folder
// Do something else
}
}
}
既知の問題:そのフォルダは実際にはファイルであるため、これが他の種類のファイルと区別する唯一の方法です。この方法では、ファイルがフォルダーであるという絶対的な確実性は得られませんが、拡張子がなく、サイズが0または正確にN x 4096Bのファイルである可能性があります。
上記で実際に言ったことを確認し、それを自分でテストするための実用的な例をいくつか示します。実行する前に、ブラウザが ドラッグアンドドロップ機能をサポート であることを確認してください。楽しんで:
これはDropping -on drop event-で動作します(これはdragoverイベントでは動作しないことに注意してください):
isDraggedItemIsFile = function(e) {
// handle FF
if (e.originalEvent.dataTransfer.files.length == 0) {
return false;
}
// handle Chrome
if (e.originalEvent.dataTransfer.items) {
if (typeof (e.originalEvent.dataTransfer.items[0].webkitGetAsEntry) == "function") {
return e.originalEvent.dataTransfer.items[0].webkitGetAsEntry().isFile;
} else if (typeof (e.originalEvent.dataTransfer.items[0].getAsEntry) == "function") {
return e.originalEvent.dataTransfer.items[0].getAsEntry().isFile;
}
}
return true;
};
$forms.on('drop', function(e) {
if (isDraggedItemIsFile(e)) {
// do something if file
} else{
// is directory
}
});
FF V49でテスト、Chrome V55、Edge V25
draggedであるページの全体のMimetypeを取得できました。 Mimetypeはフォルダでは空白のように見えるので、そのように区別できるかもしれません。
部分的なコード(Reactから抽出):
function handleDragOver(ev: DragEvent) {
ev.preventDefault();
ev.dataTransfer!.dropEffect = 'copy';
console.log(Array.from(ev.dataTransfer.items).map(i => [i.kind,i.type].join('|')).join(', '));
}
document.addEventListener('dragover',handleDragOver);
出力は次のようになります。
file|image/x-icon, file|image/jpeg, file|application/vnd.ms-Excel
ページ上に3つのファイルをドラッグすると。
ローカルホストでのみ動作するかどうかはわかりませんが、まだどこにもアップロードしていませんが、完全に動作しています。
FileReaderまたはwebkitGetAsEntry()を使用して、フォルダーからファイルを分離できます。
WebkitGetAsEntry()はie11でサポートされていないため、注意してください!
コードは次のようになります。
onDrop(event) {
let files = event.dataTransfer ? event.dataTransfer.files : 'null';
for(let i = 0, file; file = files[i]; i++) {
var reader = new FileReader();
reader.onload = function (e) {
console.log('it is a file!');
};
reader.onerror = function (e) {
console.log('it is a folder!');
};
reader.readAsText(file);
}
}