###目的
現在ファイルやディレクトリを扱う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は取得できないのでしょうか、、、
回答2件
あなたの回答
tips
プレビュー