2019-10-20
20521 ワード
HTML5 File API
HTML 5のinputタグに、
上のコードはfile DOMです.選択をサポートします.jpg、.jpge、.gif、.png接尾辞形式の画像.ファイルを選択するとinput要素がchangeイベントをトリガーします.この要素は、選択ファイルをクリックするだけでなく、ドラッグ&ドロップ選択ファイルもサポートします.ファイルをinput要素の上にドラッグ&ドロップすると、changeイベントもトリガーされます.
ファイルAPIでは、ユーザーが選択したファイルを表すオブジェクトFileを含むFilleListにアクセスできます.
file inputの使い方
正直、file
click()法によるシミュレーション
上のコードが実行されるとbuttonをクリックしてもファイル選択ウィンドウが呼び出されます.
Label要素の使用
Label要素は、
上のコードを実行し、labelの文字をクリックすると、ファイル選択ボックスがポップアップします.labelを使用すると、clickイベントを定義またはシミュレートする必要はありません.
以下はCSSで最適化したfile inputコンポーネントです.
CSSスタイル
JavaScript
ドラッグ&ドロップによるファイルの選択
file input要素はデフォルトでドラッグ&ドロップをサポートします.ドラッグ&ドロップを使用してファイルを選択する場合は、file inputを使用する必要はありません.要素を作成してdropイベントを受信すればよい.
やはり上のHTML+CSS解构です.ただし、マウスドラッグイベントを追加します.
画像のプレビューを表示
なお、これらのURLオブジェクトが不要になった場合、各オブジェクトは
FileReaderを使用したプレビューの作成
これは、上記の
ファイルのアップロード
FileReaderを使用してファイルをアップロードする
次に、ファイルアップロードの例を示します.
HTMLスケルトン:
JavaScriptコード:
CSSスタイル:
のコードでは、
Nodeを うjsはバックエンド を う:
もちろん、
Node.jsサービス が
シミュレーションプログレスバー
くのファイルのアップロードまたはダウンロードシーンには、ダウンロード/アップロードの があり、 は バーで されます.XMLHttpRequestインスタンスのuploadオブジェクトでは、ファイルのアップロード/ダウンロードの をリスニングするために
なコード:
CSS ファイルアップロード
FormDataによるファイルアップロード
form要素を使用してラップしない場合は、
HTML 5のinputタグに、
type=file
プロパティのフォームコントロールが追加されました.このコントロールを使用すると、ファイル選択ウィンドウを呼び出してファイルの内容を読み取ることができます.
上のコードはfile DOMです.選択をサポートします.jpg、.jpge、.gif、.png接尾辞形式の画像.ファイルを選択するとinput要素がchangeイベントをトリガーします.この要素は、選択ファイルをクリックするだけでなく、ドラッグ&ドロップ選択ファイルもサポートします.ファイルをinput要素の上にドラッグ&ドロップすると、changeイベントもトリガーされます.
ファイルAPIでは、ユーザーが選択したファイルを表すオブジェクトFileを含むFilleListにアクセスできます.
const fileIpt = document.getElementById("file-ipt");
// change :
fileIpt.onchange = function(){
const files = fileIpt.files; // fileList
for(let i = 0;i < files.length;i ++){
console.log(files[i]);
}
}
file inputの使い方
正直、file
要素がページに表示されている様子はあまり面白くありません.file input要素を使用するUIコンポーネントの多くは、この要素を隠し、いくつかのテクニックでファイルアップロードコンポーネントをきれいにします.click()法によるシミュレーション
const fileIpt = document.querySelector('#file-ipt');
const btn = document.querySelector(".btn");
btn.addEventListener('click',function(){
if(fileIpt){
// button , fileIpt
fileIpt.click();
}
},false);
上のコードが実行されるとbuttonをクリックしてもファイル選択ウィンドウが呼び出されます.
Label要素の使用
Label要素は、
要素と関連付けることができる.
にid属性を与える必要があります.
には、inputのidと同じ値を持つfor
属性が必要です.
上のコードを実行し、labelの文字をクリックすると、ファイル選択ボックスがポップアップします.labelを使用すると、clickイベントを定義またはシミュレートする必要はありません.
以下はCSSで最適化したfile inputコンポーネントです.
CSSスタイル
*{
padding: 0;
margin: 0;
}
.wrapper{
width: 200px;
display: flex;
flex-direction: column;
justify-content: center;
margin: 100px auto;
}
.label-file{
display: flex;
flex-direction: column;
width: 100px;
height: 100px;
border: 1.5px dashed #999999;
color: #999999;
cursor: pointer;
justify-content: center;
align-items: center;
margin-bottom: 10px;
border-radius: 6px;
}
.label-file:hover{
border: 1.5px dashed #1890ff;
transition: all 0.6s;
}
span.add{
font-size: 40px;
}
span.describe{
font-size: 16px;
}
.wrapper p{
padding: 6px 0px;
}
JavaScript
const fileIpt = document.getElementById("file-ipt");
const wrapper = document.querySelector(".wrapper");
fileIpt.addEventListener('change',function(){
const file = fileIpt.files[0];
let p = document.createElement("p"),
name = file.name;
p.innerText = name;
wrapper.appendChild(p);
},false);
ドラッグ&ドロップによるファイルの選択
file input要素はデフォルトでドラッグ&ドロップをサポートします.ドラッグ&ドロップを使用してファイルを選択する場合は、file inputを使用する必要はありません.要素を作成してdropイベントを受信すればよい.
やはり上のHTML+CSS解构です.ただし、マウスドラッグイベントを追加します.
const fileIpt = document.getElementById("file-ipt");
const wrapper = document.querySelector(".wrapper");
const dropBox = document.querySelector(".label-file");
//
function drag(e){
e.stopPropagation();
e.preventDefault();
}
function handleFiles(files){
for(let i = 0;i < files.length;i ++){
var p = document.createElement("p");
p.innerText = files[i].name;
wrapper.appendChild(p);
}
// fileIpt
fileIpt.files = files;
}
//
function drop(e){
e.stopPropagation();
e.preventDefault();
// ,drop
//
var dt = e.dataTransfer;
var files = dt.files;
handleFiles(files);
}
dropBox.addEventListener("dragenter",drag,false);
dropBox.addEventListener("dragover",drag,false);
dropBox.addEventListener("drop", drop, false);
画像のプレビューを表示
URL.createObjectURL()
の方法を使用して実施することができる.パラメータは、URLを作成するためのFile
オブジェクト、Blob
オブジェクト、またはMediaSource
オブジェクトです.上のコードに加えて、次のコードを追加します.fileIpt.onchange = function(){
const files = this.files;
var ul = document.createElement("ul");
for(let i = 0;i < files.length;i ++){
var li = document.createElement("li");
li.classList.add("imgWrapper");
ul.appendChild(li);
//
var image = new Image(200);
// url url
image.src = window.URL.createObjectURL(files[i]);
image.onload = function() {
window.URL.revokeObjectURL(this.src);
}
li.appendChild(image);
}
wrapper.appendChild(ul);
}
なお、これらのURLオブジェクトが不要になった場合、各オブジェクトは
URL.revokeObjectURL(src)
メソッドを呼び出すことによって解放される必要がある.ブラウザはドキュメントが終了すると自動的に解放されますが、最適なパフォーマンスとメモリの使用状況を得るためには、安全なタイミングで自動的に解放する必要があります.FileReaderを使用したプレビューの作成
これは、上記の
fileIpt.onchange
イベントを書き換える必要があります.fileIpt.onchange = function(){
const files = this.files;
var ul = document.createElement("ul");
for(let i = 0;i < files.length;i ++){
var li = document.createElement("li");
li.classList.add("imgWrapper");
ul.appendChild(li);
var image = new Image(200);
li.appendChild(image);
//
var reader = new FileReader();
reader.onload = (function(aimg){
return function(e){
aimg.src = e.target.result;
}
})(image);
// url
reader.readAsDataURL(files[i]);
}
wrapper.appendChild(ul);
}
reader.readAsDataURL(files[i])
メソッドは、指定されたBlobの内容を読み取ることができる.完了すると、result(e.target.result)プロパティには、読み込まれたファイルの内容を表すdata:URL形式のBase 64文字列が含まれます.ファイルのアップロード
FormData
オブジェクトまたはFileReader
を使用してファイルアップロードを実装するか、HTML 5によって提供されるFormData
を使用して実装することができる.この3つの方法を紹介します.FileReaderを使用してファイルをアップロードする
FileReader
APIは、画像プレビュー図を示す部分および使用されたことがある.アップロードファイルについては、FileReader
APIの1つの方法を使用して、readAsBinaryString(blob)
またはreadAsArrayBuffer(blob)
のファイルアップロードの目的を達成することができる.readAsDataURL(file)
メソッドはファイルにURLを生成することができ、readAsBinaryString
メソッドは指定されたBlobの内容を読み取ることができる.完了すると、resultプロパティには、読み込まれたファイルの元のバイナリデータが含まれます.一方、readAsArrayBuffer(blob)
は、指定されたBlobまたはFileコンテンツを読み込むことができ、resultプロパティには、読み込まれたファイルのデータを表すArrayBufferオブジェクトが含まれます.var reader = new FileReader();
reader.readAsArrayBuffer(blob);
reader.onload = function(e){
//
var data = e.target.result;
}
次に、ファイルアップロードの例を示します.
HTMLスケルトン:
+
Upload
JavaScriptコード:
const imgsBox = document.querySelector(".imgsBox");
const dropBox = document.querySelector(".dropBox");
const fileIpt = document.querySelector("#file-ipt");
/**
* Ajax
* @param {XMLHttpRequest} xhr
* @param {string} method
* @param {string} url
* @param {Object} data
* @param {JSON} headers
*/
function ajax(xhr,method = "GET",url,data = '',headers = {}){
return new Promise((resolve,reject) => {
xhr.open(method, url);
for(let p in headers){
xhr.setRequestHeader(p,headers[p]);
}
xhr.onreadystatechange = function () {
if(xhr.readyState === 4){
if(xhr.status === 200 || xhr.status === 304){
resolve(xhr.response);
}else{
reject("Warning!",xhr.status);
}
}
}
xhr.send(data);
});
}
/**
*
* @param {JSON} data
*/
function uploadFile(data){
const xhr = new XMLHttpRequest();
//
xhr.upload.addEventListener("progress", function (e) {
if (e.lengthComputable){
console.log((e.loaded * 100 / e.total).toFixed(2) + "%");
}
}, false);
//
xhr.upload.addEventListener("load",function(){
console.log(" !");
},false);
//
var result = ajax(xhr, "POST", "/file.php", data);
result.then((data) => console.log(data));
}
/**
*
* @param {string} imgURL
*/
function createImage(imgURL){
var div = document.createElement("div"),
box = document.createElement("div");
img = document.createElement("img"),
div.classList.add("imgWrapper");
box.classList.add("imgBox");
img.src = imgURL;
box.appendChild(img);
div.appendChild(box);
img.onload = function(){
if(img.height < img.width || img.height === img.width)
img.style.height = "100%";
else
img.style.width = "100%";
}
imgsBox.insertBefore(div,dropBox);
}
/**
*
* @param {File} file
*/
function handleFiles(file){
var name = file.name,
reader = new FileReader(),
showImgReader = new FileReader();
showImgReader.onload = function(e){
createImage(e.target.result);
}
reader.onload = function(e){
uploadFile(JSON.stringify({
name,
file: e.target.result,
}));
}
reader.readAsBinaryString(file);
showImgReader.readAsDataURL(file);
}
/**
* file change
* @param {Event} e
*/
function fileChange(e){
var fileList = this.files || e.target.files;
for(let i = 0;i < fileList.length;i ++){
handleFiles(fileList[i]);
}
}
fileIpt.addEventListener("change",fileChange,false);
CSSスタイル:
*{
padding: 0;
margin: 0;
}
div.wrapper{
height: 500px;
width: 500px;
border: 1px solid #dddddd;
margin: 100px auto;
border-radius: 10px;
}
div.imgsBox{
margin: 60px;
width: 360px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto;
}
div.dropBox{
height: 100px;
width: 100px;
border: 1.5px dashed #999999;
border-radius: 6px;
cursor: pointer;
}
div.dropBox:hover{
border: 1.5px dashed #1890ff;
transition: border .6s;
}
#file-ipt{
display: none;
}
.dropBox .add{
color: #999999;
font-size: 50px;
width: 100%;
text-align: center;
}
.dropBox .describe{
color: #999999;
width: 100%;
text-align: center;
}
.imgWrapper{
height: 90px;
width: 90px;
padding: 8px;
background-position: center;
background-size: cover;
background-repeat: no-repeat;
border-radius: 10px;
position: relative;
background-color: white;
border: 1px solid #cccccc;
display: flex;
align-items: center;
justify-content: center;
margin: 0px 10px 10px 0px;
}
.imgWrapper .imgBox{
height: 100%;
width: 100%;
overflow: hidden;
border-radius: 6px;
}
のコードでは、
FileReader
を してファイルデータを し、POST を し、JSONデータをアップロードした.データにはファイル とファイル データが まれている.Nodeを うjsはバックエンド を う:
const fs = require("fs");
const http = require("http");
http.createServer((req,res) => {
if(req.url === "/file.php"){
let data = [];
//
req.on('data',(chunk) => {
data.push(chunk);
});
req.on('end',function(){
//
var object = JSON.parse(Buffer.concat(data).toString());
//
fs.writeFileSync(`./${object.name}`,object.file,{encoding: 'binary'});
//
res.setHeader("Content-Type","text/plain");
res.end('{"status": "seccess"}');
});
}
//
if(req.url === "/"){
res.writeHead(200,{
"Content-Type": "text/html"
});
res.end(fs.readFileSync("./01.html",{encoding: "utf8"}));
}
if(req.url === "/01.js"){
res.writeHead(200,{
"Content-Type": "text/javascript",
});
res.end(fs.readFileSync('./01.js',{encoding: 'utf8'}));
}
}).listen(4000,() => {
console.log("server is running: http://localhost:4000");
});
もちろん、
readAsArrayBuffer(file)
メソッドを してファイルを み り、リクエストを することもできます.なお、この はArrayBuffer
データを する.ArrayBuffer
のデータは できません.つまり、upload(JSON.stringify({name,file}))
メソッドを してJSON.stringify
データを したため、 のようにArrayBuffer
を してデータを することはできません.データ は うしかありません:upload(e.target.result)
.Node.jsサービス が
ArrayBuffer
データを する は、Buffer.concat(data)
でファイル き みを うだけでよい.この では、 にデータを すると、ファイルの やファイル など、 ファイルの を ることができません.ファイルの を らないと、 しいファイルを することができません.もちろん、2 のリクエストを することができます.1 はファイルデータで、1 はファイル です.シミュレーションプログレスバー
くのファイルのアップロードまたはダウンロードシーンには、ダウンロード/アップロードの があり、 は バーで されます.XMLHttpRequestインスタンスのuploadオブジェクトでは、ファイルのアップロード/ダウンロードの をリスニングするために
progress
をリスニングできます.load
メソッドは、ファイルのアップロード/ダウンロードが したことを します. のコードは、ファイルアップロード のアップロードの を します.xhr.upload.addEventListener("progress",function(e){
if (e.lengthComputable){
/*
* lengthComputable ( )。 false
* loaded ( )
* total ( )
*/
console.log((e.loaded * 100 / e.total).toFixed(2) + "%");
}
},false);
なコード:
/**
*
* @param {string} tagName
* @param {string} content
* @param {string} className
*/
function createElem(tagName,content,className){
const tag = document.createElement(tagName);
tag.innerHTML = content || '';
if(className)
tag.classList.add(className);
return tag;
}
/**
*
* @param {Element} parent
* @param {Array } elems
* number 0 ,append , 1 ,insertBefore
* @param {number} position
* insertBefore ,
* @param {Element} oldElem
*/
function appendElems(parent,elems,position,oldElem){
if(position){
elems.forEach(item => {
parent.insertBefore(item,oldElem);
});
}else{
elems.forEach(item => {
parent.appendChild(item);
});
}
}
/**
*
* @param {Event} e
* @param {Object } elems
*/
function progressAnimation(e,elems){
const { div,describe,progressNum,loadBox,loadBar } = elems;
if (e.lengthComputable) {
loadBar.style.width = "0px";
imgsBox.insertBefore(div,dropBox);
appendElems(div, [progressNum, loadBox, describe]);
loadBox.appendChild(loadBar);
describe.innerText = "Upload...";
const bar_W = parseInt(window.getComputedStyle(loadBox,null).width);
var num = (e.loaded * 100 / e.total).toFixed(2);
if(num >= 90){
loadBar.style.backgroundColor = "greenyellow";
}
loadBar.style.width = num * (bar_W / 100) + 'px';
progressNum.innerText = num + "%";
}
}
function loadAnimation(loadWrapper){
loadWrapper.style.display = "none";
loadWrapper.previousElementSibling.style.display = "flex";
}
/**
*
* @param {JSON} data
*/
function uploadFile(data){
const xhr = new XMLHttpRequest();
var elems = {
div: createElem("div", '', 'loadWrapper'),
describe: createElem("span", ' ...', 'describe'),
progressNum: createElem("span", '0%', ".progressNum"),
loadBox: createElem("div", '', 'loadBox'),
loadBar: createElem("div", '', 'loadBar')
}
xhr.upload.addEventListener("progress",function(e){
progressAnimation.call(this,e,elems);
},false);
xhr.upload.addEventListener("load",function(){
loadAnimation.call(this,elems.div);
},false);
var result = ajax(xhr, "POST", "/file.php", data);
result.then((data) => console.log(data));
}
/**
*
* @param {string} imgURL
*/
function createImage(imgURL){
var div = document.createElement("div"),
box = document.createElement("div"),
img = document.createElement("img");
div.classList.add("imgWrapper");
box.classList.add("imgBox");
img.src = imgURL;
box.appendChild(img);
div.appendChild(box);
img.onload = function(){
if(img.height < img.width || img.height === img.width)
img.style.height = "100%";
else
img.style.width = "100%";
}
imgsBox.insertBefore(div,dropBox);
div.style.display = "none";
}
CSS ファイルアップロード
.loadWrapper{
height: 100px;
width: 100px;
background: white;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border: 1px solid #cccccc;
border-radius: 6px;
}
.loadWrapper .describe{
color: #999999;
}
.loadWrapper .progressNum{
color: orangered;
font-weight: bold;
}
.loadWrapper .loadBox{
width: 80px;
height: 10px;
border-radius: 5px;
border: 1px solid #cccccc;
margin: 6px 0px;
box-sizing: border-box;
overflow: hidden;
}
.loadWrapper .loadBox .loadBar{
width: 0px;
height: 20px;
background: green;
}
FormDataによるファイルアップロード
FormData
はHTML 5のAPIです.FormData
を してフォームを する を に します.
const form = document.getElementById("form");
const submitBtn = document.getElementsByClassName("submitBtn")[0];
// from FormData
const formData = new FormData(form);
function ajax(xhr, method = "GET", url, data = "", headers = {}) {
return new Promise((resolve, reject) => {
xhr.open(method, url);
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status === 200 || this.status === 304) {
resolve(this.response);
}else{
reject("Warnning!",this.status);
}
}
}
for(let p in headers){
xhr.setRequestHeader(p,headers[p]);
}
xhr.send(data);
});
}
submitBtn.addEventListener("click", async function (e) {
const xhr = new XMLHttpRequest();
var res = await ajax(
xhr,
"POST",
form.action,
// FormData
formData
);
console.log(res);
}, false);
FormData
の例は1つのMapである.中にはappend
、delete
、has
などの方法があります.FormData
を使用する場合、form要素にはenctype="multipart/form-data"
という属性が追加されます.追加しないと、生成されたデータはkey=value
形式のデータであり、file inputがある場合、ファイル内容はアップロードされません.form要素を使用してラップしない場合は、
formData.append()
メソッドを使用してデータを追加できます.append()
メソッドは、2つのパラメータを受信し、最初のパラメータはデータであり、1つの文字列であってもよいし、blobオブジェクトであってもよく、fileデータはblobに属する.2番目のパラメータはオプションで、データのファイル名を表し、文字列です.const formData = new FormData();
const file = document.getElementById("file-ipt");
formData.append(file.files[0]); //