質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.34%

  • JavaScript

    17531questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

ブラウザに対しディレクトリをドラッグ&ドロップした際の挙動

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 288
退会済みユーザー

退会済みユーザー

目的

現在ファイルやディレクトリを扱うWebサービスの開発をしています。
その過程でブラウザにディレクトリを複数単数問わずドラッグ&ドロップする処理が必要になりました。
ブラウザ側でディレクトリをドラッグ&ドロップされたとき、サーバー側には、ディレクトリ内で階層構造になっているファイルのみを取得し、ドラッグ&ドロップされたディレクトリをルートディレクトリとして、ファイル毎のフルパスとファイルそのもののデータを送る処理を作りたいです。

質問

以前もこちらで、上記仕組みに関する質問をさせていただき、現在ディレクトリ内のファイル毎のフルパスを取得することができました。
ただ、どうやってもファイル本体のデータを送信することができません。取得できているかの確認すらできていません。
どのように処理をつくると、サーバー側にファイルを送ることができますか?

具体的には、GoogleDriveのような処理をつけたいということです。

コード

こちらが、一連の処理に関わるコードになります。

            function uploadFile(fileObject) {
                let fileBinary = new FormData();
                for (let i = 0; i < fileObject.length; i++) {
                    fileBinary.append("file[]", fileObject[i]);
                }
                console.log(fileObject);
                $.ajax({
                    url: ' ',
                    type: 'POST',
                    contentType: false,
                    processData: false,
                    data: fileObject,
                    timeout: (1000 * 1800)
                }).done(data => {
                    console.log("success!");
                    console.log(data);
                }).fail(err => {
                    console.log("Oops!");
                    console.log(err);
                });
            }

            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("dropzone")
                    .addEventListener("dragover", event => {
                        event.preventDefault();
                    }, false);

            document.getElementById("dropzone")
                    .addEventListener("drop", async event => {
                        const items = event.dataTransfer.items;
                        const results = [];
                        const promise = [];
                        event.preventDefault();
                        for (const item of items) {
                            const entry = item.webkitGetAsEntry();
                            promise.push(scanFiles(entry, results));
                        }
                        await Promise.all(promise);
                        console.log(results);
                    }, false);
        <div id="dropzone">
                <button class="btn btn-primary btn-block" id="cover" data-toggle="collapse" data-target="#collapseSample1">
                    ここにファイルを
                    <br>
                    ドロップしてください
                </button>
        </div>
            #dropzone {
                text-align: center;
                width: 1000px;
                height: 70px;
                margin: 10px;
                padding: 10px;
                border-radius: 10px;
            }

この処理ではuploadFileは呼ばれていませんが、uploadFileに適切なオブジェクトを与え、バイナリデータがサーバー(PHP)に送られ、$_FILEで取得できるところまでできるようにしたいです。
ajaxのurlは意図的に未記入にしています。実際はサーバのURLを記入し、すでにデータを送って試しています。

試したこと

dropのEventListener内に、

const files = event.dataTransfer.files;
uploadFile(files);


と与えると、ファイルの時は期待する動作をしてくれるのですが、ディレクトリには対応してくれません。

追記

「サーバー側には、ディレクトリ内で階層構造になっているファイルのみを取得し、ドラッグ&ドロップされたディレクトリをルートディレクトリとして、ファイル毎のフルパスとファイルそのもののデータを送る」
とかいてありますが、サーバー側でのデータ管理は、
フルパス:ファイルデータ
のようになっており、実際に扱われているディレクトリなどの階層構造のようなものではないため、送りたいデータがフルパスとファイルデータである、という理由です。

追・追記

 const reader = new FileReader();
                        const files = event.dataTransfer.files;
                        console.log(files);
                        reader.onload = () => {
                            console.log(reader.result);
                        };
                        reader.readAsText(files[0]);
                        reader.readAsText(results[0]);


のコードをdropのEventListenerのコードの、下部のconsole.logの下に追加し、実行したところ、filesの方はテキストを表示できているのに対し、resultsの方はblobじゃないとエラーが出ました。
もしかしてdataTransfer.itemsではファイルBlobは取得できないのでしょうか、、、

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mts10806

    2018/05/31 19:27

    FormData();\ ←これはコピペミスでしょうか?

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2018/05/31 19:28

    申し訳ございません。コピペミスです、修正します。

    キャンセル

回答 2

check解決した方法

+1

自己解決いたしました。scanFile内の以下のcaseにて、

case (entry.isFile) :
    tmpObject.push(entry);
    break;


entryに対しfileメソッドを呼ぶとファイルの中身を取得できました。

entry.file(file => {
    const reader = new FileReader();
    reader.readAsText(file);
    reader.onload = () => {
        console.log(reader.result);
    };
});

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

<input type="file">でもディレクトリごと送ることはできないので
難しいと思います

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/02 09:55

    難しかったです。
    ですが、しっかりこのAPIのドラフトを読み込み、自己解決することができました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • JavaScript

    17531questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。