22
13

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 5 years have passed since last update.

JavaScriptを使ってWebブラウザにディレクトリをドラッグ&ドロップしよう!

Last updated at Posted at 2018-06-01


RHEMS技術研究室の西田です!
今回ブラウザ上にファイルまたはディレクトリをドラッグ&ドロップしてサーバにアップロードする、という機能が必要になったので、その際にハマったことや身についたナレッジなどを共有していきたいと思います!

#tl;dr.
・Webブラウザにファイルをドラッグ&ドロップする機能は簡単に実装できた
・複数のディレクトリをドラッグ&ドロップする機能は難しい。。。
・そうだ File and Directory Entry API を使おう!

#現在の進捗状況
・[単数|複数]の[ディレクトリ|ファイル]をドラッグ&ドロップで取得できた!
あれ?中身が見れない!もしかしてバイナリ取得できてない???どうやってみるんだ。。。
・やっぱり取得できてるじゃん!やったね!

#実装
コードは以下のようになっています。

HTML/CSS
<div id="droparea">
    <button class="btn btn-primary btn-block" id="cover">
        ここにファイルを
        <br>
        ドロップしてください
    </button>
</div>

<style>
    #droparea {
        padding: 100px 25%;
    }

    #cover {
        width: 100%;
        height: 70px;
    }
</style>
JavaScript
async function scanFiles(entry, tmpObject) {
    switch (true) {
        case (entry.isDirectory) :
            const entryReader = entry.createReader();
            const entries = await new Promise(resolve => {
                entryReader.readEntries(entries => resolve(entries));
            });
            await Promise.all(entries.map(entry => scanFiles(entry, tmpObject)));
            break;
        case (entry.isFile) :
            tmpObject.push(entry);
            break;
    }
}

document.getElementById("droparea")
    .addEventListener("dragover", event => {
        event.preventDefault();
    }, false);

document.getElementById("droparea")
    .addEventListener("drop", async event => {
        event.preventDefault();
        const items = event.dataTransfer.items;
        const results = [];
        const promise = [];
        for (const item of items) {
            const entry = item.webkitGetAsEntry();
            promise.push(scanFiles(entry, results));
        }
        await Promise.all(promise);
        console.log(results); //テスト表示
/*--------------------追加コード--------------------*/
        for(let result of results) {
            result.file(file => {
                const reader = new FileReader();
                reader.readAsText(file);
                reader.onload = () => {
                    console.log(result.fllPath);
                    console.log(file);
                    console.log(reader.result);
                };
            });
        }
/*-----------------------------------------------*/

    }, false);

追加コード部の処理がFileEntryから実体を取得し、表示するコードです。
この処理をゴニョゴニョすることで、サーバ側で同一ディレクトリ構造を復元したり、GoogleDriveのようにブラウザ上でディレクトリを扱えたり出来るようになります。
フルパスも中身も取得できてる上、複数選択しようが単数で投げようが、関係なくすべて処理してくれます。
ここに、条件を付け加えるだけで、文章のみ受け取ったり、画像だけ不可なども可能になります。
また、この機能は現在非標準ですが、GoogleChrome、Opera、FireFoxでの動作を確認しています。
Windowsマシンが届き次第、EdgeやIE(多分未対応)での動作も試してみます。

22
13
0

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
22
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?