web應用的痛點就是不能操作計算機上的檔案。File API和Blob API可以安全通路到用戶端上的檔案。
File類型
現在我們可以在html表單中直接通路檔案,比如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="file">
</body>
</html>
效果如圖:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SO1ITO4kDOhVWNzUDNyEGOzYzXxEDNxADMzAzLcJTMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
當我們選擇檔案後,可以讀出檔案得到名稱:
選中後的檔案中,每一個File對象中都隻有一些隻讀屬性,比如name、size和type:
FileReader類型
FileReader類型是一種異步檔案讀取機制,提供了集中讀取檔案資料的方法:
readAsText(file,encoding):從檔案中讀取純文字内容并且儲存在result屬性中,第二個參數是表示編碼,可選參數。
readAsDataURL(file):讀取檔案并且将内容的資料URI儲存在result屬性中。
readAsBinaryString(file):讀取檔案并且把每一個字元的二進制資料儲存在result屬性。
readAsArrayBuffer(file):讀取檔案并且把内容以ArrayBuffer形式儲存在result中。
在讀取檔案中,會觸發幾個事件:progress、error和load,表示進度、發生錯誤和讀取完成。
progress事件每50毫秒就會觸發一次,在這期間可以讀取FileReader的result屬性;
error事件,在無法讀取檔案的時候觸發,error屬性是一個對象,隻包含一個屬性:code。這個錯誤碼的值可能是1(未找到檔案)、2(安全錯誤)、3(讀取被中斷)、4(檔案不可讀)或5(編碼錯誤)
load事件會在成功加載後觸發,如果error事件觸發,那麼不會觸發load事件
比如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="file" id="file">
<div type="text" id="output"></div>
<div id="progress"></div>
<script>
let filesList = document.getElementById("file");
filesList.addEventListener("change", (event) => {
let info = "",
output = document.getElementById("output"),
progress = document.getElementById("progress"),
files = event.target.files,
type = "default",
reader = new FileReader();
if (/image/.test(files[0].type)) {
reader.readAsDataURL(files[0]);
type = "image";
} else {
reader.readAsText(files[0]);
type = "text";
}
reader.onerror = function() {
output.innerHTML = "Could not read file, error code is " +
reader.error.code;
};
reader.onprogress = function(event) {
if (event.lengthComputable) {
console.log(`${event.loaded}/${event.total}`)
progress.innerHTML = `${event.loaded}/${event.total}`;
}
};
reader.onload = function() {
let html = "";
switch(type) {
case "image":
html = `<img src="${reader.result}">`;
break;
case "text":
html = reader.result;
break;
}
output.innerHTML = html;
};
});
</script>
</body>
</html>
Blob
Blob是表示二進制大對象,是JavaScript對不可修改的二進制資料的封裝類型,包含字元串的數組、ArrayBuffers、ArrayBufferViews,
Blob對象有一個size屬性和type屬性,slice方法用于進一步切分資料,另外也可以使用FileReader從Blob中讀取資料。隻讀取一部分檔案可以節省時間,比如現在隻讀取檔案的前10個位元組:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="file" id="file">
<div type="text" id="output"></div>
<div id="progress"></div>
<script>
let filesList = document.getElementById("files-list");
filesList.addEventListener("change", (event) => {
let info = "",
output = document.getElementById("output"),
progress = document.getElementById("progress"),
files = event.target.files,
reader = new FileReader(),
blob = blobSlice(files[0], 0, 10);
if (blob) {
reader.readAsText(blob);
reader.onerror = function () {
output.innerHTML = "Could not read file, error code is " +
reader.error.code;
};
reader.onload = function () {
output.innerHTML = reader.result;
};
} else {
console.log("Your browser doesn't support slice().");
}
});
</script>
</body>
</html>
Blob URL
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="file" id="file" multiple>
<div type="text" id="output"></div>
<div id="progress"></div>
<script>
let filesList = document.getElementById("file");
filesList.addEventListener("change", (event) => {
let info = "",
output = document.getElementById("output"),
progress = document.getElementById("progress"),
files = event.target.files,
reader = new FileReader(),
url=window.URL.createObjectURL(files[0]);
console.log("url",url)
if (url) {
if (/image/.test(files[0].type)) {
output.innerHTML=`<img src="${url}">`;
} else {
output.innerHTML = "Not an image.";
}
} else {
output.innerHTML = "Your browser doesn't support object URLs.";
}
});
</script>
</body>
</html>