JavaScriptフィルリストオブジェクトのフォルダー/ディレクトリの検出
-
28-10-2019 - |
質問
私は最近、HTML5の機能の一部を使用して、デスクトップからドラッグアンドドロップを介してフォームでファイルをアップロードできるようにするMoodleにいくつかのコードを提供しました(コードのコア部分はこちらです。 https://github.com/moodle/moodle/blob/master/lib/form/dndupload.js 参考のため)。
これは、ユーザーがいる場合を除いて、うまく機能しています ドラッグ a フォルダー /ディレクトリ 実際のファイルの代わりに。その後、ガーベッジはサーバーにアップロードされますが、ファイル名はフォルダーに一致します。
私が探しているのは、簡単で信頼できる方法です 探知 aの存在 フォルダ の中に フィルリスト オブジェクト、だから私はそれをスキップすることができます(そしておそらくフレンドリーなエラーメッセージも返します)。
MDNのドキュメントと、より一般的なWeb検索を調べましたが、何も表示されませんでした。また、Chrome開発者ツールのデータを調べましたが、 'タイプ' ファイルのオブジェクトは一貫して設定されています "" フォルダー用。ただし、これが最も信頼性の高いクロスブラウザー検出方法であると私は確信していません。
誰かがより良い提案をしていますか?
解決
頼ることはできません file.type
. 。拡張機能のないファイルにはタイプがあります ""
. 。でテキストファイルを保存します .jpg
拡張してファイルコントロールにロードすると、そのタイプは次のように表示されます image/jpeg
. 。そして、「somefolder.jpg」という名前のフォルダーには、そのタイプもあります image/jpeg
.
でファイルを読んでみてください FileReader
. 。ディレクトリがドラッグされている場合、 FileReader
上昇します error
イベント:
var reader = new FileReader();
reader.onload = function (e) {
// it's a file
};
reader.onerror = function (e) {
// it's a directory
};
reader.readAsText(file);
幸いなことに、IE11では、ディレクトリがドロップされると、 e.dataTransfer.files
コレクションは空です。
Chromeは追加のプロパティを公開します e.dataTransfer
呼び出されました items
のコレクションを含む DataTransferItem
オブジェクト。これらの各オブジェクトでは、呼び出すことができます item.webkitGetAsEntry()
, 、それが返されます Entry
物体。 Entry
オブジェクトにはプロパティがあります isDirectory
と isFile
:
// Chrome only
if (e.dataTransfer.items && e.dataTransfer.items.length) {
[].forEach.call(e.dataTransfer.items, function(item) {
var entry = item.webkitGetAsEntry();
if (entry && entry.isFile) {
var file = item.getAsFile(); // same as object in e.dataTransfer.files[]
// do something with the file
}
}
}
興味深いことに、私の実験では、私が見たすべてのフォルダーが持っていました File.size % 4096
ゼロとして。ただし、もちろん、一部のファイルにもそれがあります。 File.size
ファイルが実際にフォルダーであるかどうかの信頼できる指標ではありません。
他のヒント
私もこの問題に出くわしましたが、以下が私の解決策です。基本的に、私は2つのプロングされたアプローチを取りました:
(1) ファイルオブジェクトのサイズが大きいかどうかを確認し、1MBを超える場合は本物のファイルであると考えてください(フォルダー自体がそれほど大きくないと仮定しています)。(2) ファイルオブジェクトが1MBより小さい場合は、FileReaderの「readasarraybuffer」メソッドを使用して読みます。成功した読み取りは「onload」を呼び出しますが、これはファイルオブジェクトが本物のファイルであることを示していると思います。失敗した読み取りは「Onerror」を呼び出し、ディレクトリと考えています。これがコードです:
var isLikelyFile = null;
if (f.size > 1048576){ isLikelyFile = false; }
else{
var reader = new FileReader();
reader.onload = function (result) { isLikelyFile = true; };
reader.onerror = function(){ isLikelyFile = false; };
reader.readAsArrayBuffer(f);
}
//wait for reader to finish : should be quick as file size is < 1MB ;-)
var interval = setInterval(function() {
if (isLikelyFile != null){
clearInterval(interval);
console.log('finished checking File object. isLikelyFile = ' + isLikelyFile);
}
}, 100);
これをFF 26、Chrome 31、およびSafari 6および3つのブラウザで、ディレクトリを読み込もうとするときに「Onerror」と呼びました。誰かがこれが失敗する場合のユースケースを考えることができるかどうかを教えてください。
電話を提案します FileReader.readAsBinaryString
に File
物体。 Firefoxでは、これは例外を提起します File
aです Directory
. 。私はこれを行います File
Gilly3によって提案された条件を満たします。
で私のブログ投稿をご覧ください http://hs2n.wordpress.com/2012/08/13/detecting-folders-in-html-drop-area/ 詳細については。
また、Google Chromeのバージョン21は、ドロップフォルダーをサポートするようになりました。ドロップされたアイテムがフォルダーであるかどうかを簡単に確認し、コンテンツも読み取ることができます。
残念ながら、古いChromeバージョン用の(クライアント側)ソリューションはありません。
もう1つの注意点は、未知の拡張子を持つファイルのタイプが「」であることです。 test.blahという名前のファイルをアップロードしてみてください。タイプは空になります。そして... test.jpgという名前のフォルダーをドラッグしてドロップしてみてください - タイプは「image/jpeg」に設定されます。 100%正しいために、タイプだけに依存することはできません(または、実際に)。
私のテストでは、フォルダーは常にサイズ0でした(64ビットのWindows 7以下のLinuxミント(Ubuntuの基本的に)のFFとChromeです。したがって、私のフォルダーチェックはサイズが0であるかどうかを確認しています。私たちの環境では、0バイトファイルをアップロードしたくないので、0バイトの場合、メッセージは「スキップ-0バイト(またはフォルダー)」として戻ってきます
参考までに、この投稿では、ファイルタイプを検出するためにChromeでDatAtransfer APIを使用する方法を説明します。 http://updates.html5rocks.com/2012/07/drag-and-drop-a-folder-onto-chrome-now-abailable