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

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

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

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

Q&A

解決済

2回答

2853閲覧

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

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

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

0グッド

1クリップ

投稿2018/05/31 10:17

編集2018/05/31 10:47

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

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

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

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

JavaScript

1 function uploadFile(fileObject) { 2 let fileBinary = new FormData(); 3 for (let i = 0; i < fileObject.length; i++) { 4 fileBinary.append("file[]", fileObject[i]); 5 } 6 console.log(fileObject); 7 $.ajax({ 8 url: ' ', 9 type: 'POST', 10 contentType: false, 11 processData: false, 12 data: fileObject, 13 timeout: (1000 * 1800) 14 }).done(data => { 15 console.log("success!"); 16 console.log(data); 17 }).fail(err => { 18 console.log("Oops!"); 19 console.log(err); 20 }); 21 } 22 23 async function scanFiles(entry, tmpObject) { 24 switch (true) { 25 case (entry.isDirectory) : 26 const entryReader = entry.createReader(); 27 const entries = await new Promise(resolve => { 28 entryReader.readEntries(entries => resolve(entries)); 29 }); 30 await Promise.all(entries.map(entry => scanFiles(entry, tmpObject))); 31 break; 32 case (entry.isFile) : 33 tmpObject.push(entry); 34 break; 35 } 36 } 37 38 document.getElementById("dropzone") 39 .addEventListener("dragover", event => { 40 event.preventDefault(); 41 }, false); 42 43 document.getElementById("dropzone") 44 .addEventListener("drop", async event => { 45 const items = event.dataTransfer.items; 46 const results = []; 47 const promise = []; 48 event.preventDefault(); 49 for (const item of items) { 50 const entry = item.webkitGetAsEntry(); 51 promise.push(scanFiles(entry, results)); 52 } 53 await Promise.all(promise); 54 console.log(results); 55 }, false);

HTML

1 <div id="dropzone"> 2 <button class="btn btn-primary btn-block" id="cover" data-toggle="collapse" data-target="#collapseSample1"> 3 ここにファイルを 4 <br> 5 ドロップしてください 6 </button> 7 </div>

CSS

1 #dropzone { 2 text-align: center; 3 width: 1000px; 4 height: 70px; 5 margin: 10px; 6 padding: 10px; 7 border-radius: 10px; 8 }

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

###試したこと
dropのEventListener内に、

JavaScript

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

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

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

###追・追記

JavaScript

1 const reader = new FileReader(); 2 const files = event.dataTransfer.files; 3 console.log(files); 4 reader.onload = () => { 5 console.log(reader.result); 6 }; 7 reader.readAsText(files[0]); 8 reader.readAsText(results[0]);

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2018/05/31 10:27

FormData();\ ←これはコピペミスでしょうか?
退会済みユーザー

退会済みユーザー

2018/05/31 10:28

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

回答2

0

ベストアンサー

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

JavaScript

1case (entry.isFile) : 2 tmpObject.push(entry); 3 break;

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

JavaScript

1entry.file(file => { 2 const reader = new FileReader(); 3 reader.readAsText(file); 4 reader.onload = () => { 5 console.log(reader.result); 6 }; 7});

投稿2018/06/02 00:59

編集2018/06/02 01:00
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

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

投稿2018/05/31 11:00

yambejp

総合スコア114829

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/06/02 00:55

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問