H 5ドラッグ&ドロップ非同期ファイルアップロードの2——アップロード進捗監視
7973 ワード
前の《H 5ドラッグ&ドロップ+FormDataインタフェース+NodeJS,完全非同期ファイルアップロード(一)》では、ドラッグ&ドロップファイルのアップロードの流れ全体が通じましたが、実際の使用シーンからはまだ差があります.ここでは、実際にシーンを使用するために必要な機能をいくつか追加し、実際に使用するためにさらに一歩進みます.
機能の追加アップロードするファイルのリストを表示します. はアップロードするファイルの削除をサポートします. はuploadを用いる.onprogressはアップロードの進捗状況を表示します. はアップロードの中断をサポートする.
upload.progress
XMLHttpRequest.uploadメソッドは、アップロードの進行状況を表すXMLhttpRequestUploadオブジェクトを返します.このオブジェクトは不透明ですが、XMLH T p RequestEventTargetとして、イベントをバインドすることで進捗状況を追跡できます.onprogresは、データ転送の傍受中です(このイベントを傍受することで、アップロードの進捗状況が得られます).
MDNより抜粋
実現構想.
ファイルをアップロードエリアにドラッグ&ドロップすると、ファイルを1つのファイル配列に保存し、ファイル関連情報と削除ボタンを追加して表示し、削除ボタンをクリックしてファイル配列の対応するファイル要素を削除し、アップロードボタンをクリックしてファイル配列を巡り、アップロード待ちファイルのアップロードを開始し、削除ボタンをクリックするとファイルアップロードを中止する.
コード#コード#
ここでコードは終了し、完全なコードはGithubを表示できます.ローカルアップロードなので、テスト時に大きなファイルを使ったり、アップロードを制限したりすることができます.
終わりの言葉
これらの新しいAPIにより、ファイルのドラッグ&ドロップアップが簡単になります.残念ながら、低バージョンのIEはサポートされていません.低バージョンのIEはFalshを使ってファイルのアップロードができるそうです.具体的にはどのように実現されているのか、次の編で検討してみましょう.
機能の追加
upload.progress
XMLHttpRequest.uploadメソッドは、アップロードの進行状況を表すXMLhttpRequestUploadオブジェクトを返します.このオブジェクトは不透明ですが、XMLH T p RequestEventTargetとして、イベントをバインドすることで進捗状況を追跡できます.onprogresは、データ転送の傍受中です(このイベントを傍受することで、アップロードの進捗状況が得られます).
MDNより抜粋
実現構想.
ファイルをアップロードエリアにドラッグ&ドロップすると、ファイルを1つのファイル配列に保存し、ファイル関連情報と削除ボタンを追加して表示し、削除ボタンをクリックしてファイル配列の対応するファイル要素を削除し、アップロードボタンをクリックしてファイル配列を巡り、アップロード待ちファイルのアップロードを開始し、削除ボタンをクリックするとファイルアップロードを中止する.
コード#コード#
//
.drop-area{
margin:auto;
width: 500px;
height: 500px;
border:1px pink dashed;
}
.close-btn{
cursor: pointer;
}
.close-btn:after{
float: right;
content: 'X';
color: red;
}
#fileList{
width: 95%;
}
.process-bar{
position: relative;
margin: 0 10px 0 10px;
width: 198px;
height: 18px;
display: none;
text-align: center;
line-height: 20px;
color: #6dbfff;
border-radius: 3px;
border: 1px solid #1483d8;
background: #fff;
}
.success .process-bar,
.uploading .process-bar{
display: inline-block;
}
.process-bar .process-text{
position: relative;
z-index: 1;
}
.process-bar .process-rate{
position: absolute;
width: 0;
height: 100%;
left: 0;
top: 0;
border-radius: 3px;
background: #1483d8;
}
.file-list .success .process-text,
.file-list .success .close-btn:after,
.file-list .error .process-text,
.file-list .error .close-btn:after{
display: none;
}
.success .process-bar :after,
.error .process-bar :after{
content:'success';
position: absolute;
margin: auto;
left: 0;
right: 0;
z-index: 2;
}
.error .process-bar:after{
content: "error";
color: red;
}
//Javascript
let filesSet = []; //
let fileList = document.getElementById('fileList'); // DOM
/**
* frag
* DOM,
* https://developer.mozilla.org/zh-CN/docs/Web/API/Document/createDocumentFragment
*/
let frag = document.createDocumentFragment();
let barDom = createProccessBar(); // DOM
let submit = document.getElementById("submit") //
/* */
function dragover_hander (event) {
/* dragover drop
, html 、
*/
event.preventDefault();
}
/* */
function drop_hander (event) {
event.preventDefault(); //
var files = event.dataTransfer.files; // dataTransfer
for(let file of files) { //
// DOM, file element ,
file.element = createFileDom(file, filesSet.length)
// DOM, file processBar ,
file.processBar = filesSet.length?barDom.cloneNode(true):barDom;
// DOM
file.element.appendChild(file.processBar);
//file
filesSet.push(file);
// DOM frag
frag.appendChild(file.element);
}
// div
fileList.appendChild(frag)
}
/**
* DOM
* file ,
* index ,
*/
function createFileDom (file, index) {
let p = document.createElement('p');
//file.name
// , for...in file
let text = document.createTextNode(file.name);
let span = document.createElement("span");
span.setAttribute('index', index); // index
span.className = 'close-btn';
p.appendChild(text);
p.appendChild(span);
return p; // DOM
}
/**
* DOM,
* DOM , clone(true)
* @return {[type]} [description]
*/
function createProccessBar() {
let bar = document.createElement("span");
let rate = document.createElement("span");
let text = document.createElement("span");
bar.className = "process-bar";
rate.className = "process-rate";
text.className = "process-text";
text.innerText="0%";
bar.appendChild(text);
bar.appendChild(rate);
return bar;
}
// ,
fileList.addEventListener('click', (evt)=>{
let index = evt.target.getAttribute('index'); // index
if (index) { // index ,
if (filesSet[index].unloading && filesSet[index].req) { //
filesSet[index].req.abort(); //
filesSet[index].unloading = false; // false
} else { //
filesSet[index].element.remove(); // DOM
filesSet[index].element = null; // DOM
filesSet[index].processBar = null;// DOM
delete filesSet[index];//
}
}
})
submit.addEventListener('click',function(){//
// for...in ,
for(let key in filesSet){
// ,
if (filesSet[key].unloading || filesSet[key].uploaded) continue;
filesSet[key].unloading = true; //
// Promise,
initUpload(filesSet[key]).then(file => {
//
file.element.className = "success"; //UI
file.uploaded = true; //
}).catch((file, err) => {
file.element.className = "error"; //UI
// ,
filesSet[key].unloading = false;
})
}
})
/**
* Promise
* @param {[type]} file
*/
function initUpload(file){
return new Promise((res, rej) => {
let formData = new FormData();// FormData
let req = new XMLHttpRequest();// XHR
let reta = file.processBar.querySelector('.process-rate');// DOM
let text = file.processBar.querySelector('.process-text');// DOM
let pre;//
//
req.upload.onprogress =function(data){
pre = (data.loaded/data.total*100).toFixed(2);//
reta.style.width = pre +'%';//
text.innerText = pre +'%' ;//
}
//
req.onreadystatechange = function () {
if (req.readyState !==4 ) return ;
if (req.status === 200 ){
// ,
res(file, req)
} else {
// ,
rej(file, req)
}
}
formData.append('file',file); // append file
req.open('POST', '/process_post'); //
req.send(formData); //
file.req = req; // req ,
//
file.element.className = "uploading"
})
}
ここでコードは終了し、完全なコードはGithubを表示できます.ローカルアップロードなので、テスト時に大きなファイルを使ったり、アップロードを制限したりすることができます.
終わりの言葉
これらの新しいAPIにより、ファイルのドラッグ&ドロップアップが簡単になります.残念ながら、低バージョンのIEはサポートされていません.低バージョンのIEはFalshを使ってファイルのアップロードができるそうです.具体的にはどのように実現されているのか、次の編で検討してみましょう.