15

私は最近、HTML5 の機能の一部を使用して、デスクトップからドラッグ アンド ドロップでファイルをフォームにアップロードできるようにするコードを Moodle に提供しました (コードのコア部分はこちら: https://github.com/moodleです)。 /moodle/blob/master/lib/form/dndupload.js参照)。

ユーザーが実際のファイルの代わりにフォルダー/ディレクトリをドラッグする場合を除いて、これはうまく機能しています。次に、ガベージがサーバーにアップロードされますが、ファイル名はフォルダーと一致します。

私が探しているのは、FileListオブジェクト内のフォルダーの存在を検出するための簡単で信頼性の高い方法であるため、それをスキップできます (おそらくわかりやすいエラー メッセージも返されます)。

MDN のドキュメントと、より一般的な Web 検索を調べましたが、何も見つかりませんでした。また、Chrome 開発者ツールのデータを調べたところ、ファイル オブジェクトの「タイプ」はフォルダーに対して一貫して「」に設定されているようです。ただし、これが最も信頼性の高いクロスブラウザー検出方法であるとは確信していません。

誰にもより良い提案がありますか?

4

7 に答える 7

24

に頼ることはできませんfile.type。拡張子のないファイルのタイプは""。です。拡張子が付いたテキストファイルを保存.jpgしてファイルコントロールにロードすると、そのタイプはとして表示されimage/jpegます。また、「someFolder.jpg」という名前のフォルダのタイプも。になりimage/jpegます。

代わりに、ファイルの最初のバイトを読み取ってみてください。最初のバイトを読み取ることができる場合は、ファイルがあります。エラーがスローされた場合は、おそらくディレクトリがあります。

try {
    await file.slice(0, 1).arrayBuffer();
    // it's a file!
}
catch (err) {
    // it's a directory!
}

IE11をサポートするという不幸な立場にある場合、ファイルにはarrayBufferメソッドがありません。オブジェクトに頼る必要がありFileReaderます:

// use this code if you support IE11
var reader = new FileReader();
reader.onload = function (e) {
    // it's a file!
};
reader.onerror = function (e) {
    // it's a directory!
};
reader.readAsArrayBuffer(file.slice(0, 1));
于 2012-01-13T21:24:58.877 に答える
8

私もこの問題に遭遇しました。以下が私の解決策です。基本的に、私は 2 つの方面からのアプローチを取りました。

(1) File オブジェクトのサイズが大きいかどうかを確認し、1MB を超える場合は正規のファイルであると見なします (フォルダー自体がそれほど大きくないと仮定しています)。 (2) File オブジェクトが 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」を呼び出しました。これが失敗するユースケースを誰かが考えられるかどうか教えてください。

于 2014-01-02T01:00:40.660 に答える
2

オブジェクトを呼び出すことを提案FileReader.readAsBinaryStringFileます。Firefox では、 が の場合に例外Fileが発生しDirectoryます。Fileがgilly3によって提案された条件を満たしている場合にのみ、これを行います。

詳細については、 http://hs2n.wordpress.com/2012/08/13/detecting-folders-in-html-drop-area/にある私のブログ投稿を参照してください。

また、Google Chrome のバージョン 21 では、フォルダーのドロップがサポートされるようになりました。ドロップされたアイテムがフォルダーであるかどうかを簡単に確認し、その内容を読み取ることもできます。

残念ながら、古いバージョンの Chrome に対する (クライアント側の) ソリューションはありません。

于 2012-08-13T11:57:48.400 に答える
0

参考までに、この投稿では、Chrome で dataTransfer API を使用してファイル タイプを検出する方法について説明します

于 2013-07-29T18:47:44.197 に答える
0

もう 1 つの注意点は、不明な拡張子を持つすべてのファイルの type が "" であることです。test.blah という名前のファイルをアップロードしてみてください。タイプは空になります。そして... test.jpg という名前のフォルダをドラッグ アンド ドロップしてみてください - タイプは「image/jpeg」に設定されます。100% 正確に言うと、型だけに依存することはできません (または、依存したとしても、実際には)。

私のテストでは、フォルダーのサイズは常に 0 でした (64 ビット Windows 7 の FF および Chrome と Linux Mint (本質的には Ubuntu) で)。そのため、私のフォルダー チェックはサイズが 0 であるかどうかをチェックするだけで、私にとってはうまくいくようです。また、0 バイトのファイルをアップロードしたくないので、0 バイトの場合、「スキップ - 0 バイト (またはフォルダー)」というメッセージが返されます。

于 2012-09-13T19:25:03.887 に答える