Эта статья взята из"Бой файловых операций FileAPI", остальные серии помещаются вGithub
Добро пожаловать в Exchange и Star
представлять
HTML5 предоставляет нам спецификации, связанные с File API. В основном участвуетФайловый интерфейса такжеОбъект FileReader.
В этой статье рассматриваются общие операции с файлами во внешнем интерфейсе при разработке, такие как обнаружение совместимости, выбор файла, чтение атрибутов, чтение файла, мониторинг хода выполнения, загрузка больших сегментов файлов и загрузка с помощью перетаскивания.
Готов к работе
Во-первых, наш файл исходит из<input>Список файлов, выбранных на вкладке. Итак, подготовьте следующий HTML-код:
<input type="file" id="files" multiple />
<div id="list"></div>
<div id="images"></div>
<!-- File API相关操作写在了script.js中 -->
<script src="./script.js"></script>
Проверить совместимость
Файловые объекты представляют собой особый тип BLOB-объектов. При входе в скрипт следует проверить, поддерживает ли текущий браузер File API:
if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
throw new Error("当前浏览器对FileAPI的支持不完善");
}
Выбор файла монитора
Для типа для типа файла<input>тег, который срабатывает при выборе файлаchangeмероприятие. Информация о файле, выбранная пользователем, также будет передана в первый параметр функции обратного вызова.
function handleFileSelect(event) {
const { files } = event.target;
if (!files.length) {
console.log("没有选择文件");
return;
}
console.log("选中的文件信息是:", files);
}
document
.querySelector("#files")
.addEventListener("change", handleFileSelect, false);
Свойства файла - Файл
event.target.filesЯвляетсяFileListобъект, представляющий собойFileСписок объектов.
Каждый объект файла содержит свойства выбранного соответствующего файла. Обычно используется:
- имя: имя файла
- тип: тип файла
- размер: размер файла
Ниже с помощью атрибута type отфильтруйте файлы, не относящиеся к типу изображения, и отобразите только информацию о файлах типа изображения:
function handleFileSelect(event) {
const { files } = event.target;
if (!files.length) {
console.log("没有选择文件");
return;
}
const innerHTML = [];
const reImage = /image.*/;
for (let file of files) {
if (!reImage.test(file.type)) {
continue;
}
innerHTML.push(
`
<li>
<strong>${file.name}</strong>
(${file.type || "n/a"}) -
${file.size} bytes
</li>
`
);
}
document.querySelector("#list").innerHTML = `<ul>${innerHTML.join("")}</ul>`;
}
Прочитать файл - FileReader
В качестве примера возьмите чтение изображений, прочитайте и отобразите файлы всех типов изображений.
Чтение файла требует использованияFileReaderобъект, который обычно использует 3 метода обратного вызова:
- onload: чтение файла завершено
- onloadstart: начинается загрузка файла
- onprogress : срабатывает во время загрузки файла
а такжеImageАналогично перед чтением файла нужно привязать обработку событий. Его операции чтения: readAsArrayBuffer, readAsDataURL, readAsBinaryString, readAsText. Переданный параметрFileобъект.
Так в чем же разница между этими методами?Различные методы чтения, callback-событияonloadполученоevent.target.resultне то же самое. Например,readAsDataURLЕсли вы читаете, Результат - это URL-адрес изображения.
Ниже приведен пример чтения файла изображения и его отображения:
function handleFileSelect(event) {
let { files } = event.target;
if (!files.length) {
return;
}
let vm = document.createDocumentFragment(),
re = /image.*/,
loaded = 0, // 完成加载的图片数量
total = 0; // 总共图片数量
// 统计image文件数量
for (let file of files) {
re.test(file.type) && total++;
}
// onloadstart回调
const handleLoadStart = (ev, file) =>
console.log(`>>> Start load ${file.name}`);
// onload回调
const handleOnload = (ev, file) => {
console.log(`<<< End load ${file.name}`);
const img = document.createElement("img");
img.height = 250;
img.width = 250;
img.src = ev.target.result;
vm.appendChild(img);
// 完成加载后,将其放入dom元素中
if (++loaded === total) {
document.querySelector("#images").appendChild(vm);
}
};
for (let file of files) {
if (!re.test(file.type)) {
continue;
}
const reader = new FileReader();
reader.onloadstart = ev => handleLoadStart(ev, file);
reader.onload = ev => handleOnload(ev, file);
// 读取文件对象
reader.readAsDataURL(file);
}
}
document
.querySelector("#files")
.addEventListener("change", handleFileSelect, false);
Следите за ходом чтения
При наблюдении за ходом чтения в основном выполняется обработка файлов на объекте FileReader.onprogressмероприятие.
В следующем примере откройте файл большего размера, чтобы увидеть эффект (в противном случае он будет прочитан целиком):
function handleFileSelect(event) {
let { files } = event.target;
if (!files.length) {
return;
}
const handleLoadStart = (ev, file) =>
console.log(`>>> Start load ${file.name}`);
const handleProgress = (ev, file) => {
if (!ev.lengthComputable) {
return;
}
// 计算进度,并且以百分比形式展示
const percent = Math.round((ev.loaded / ev.total) * 100);
console.log(`<<< Loding ${file.name}, progress is ${percent}%`);
};
for (let file of files) {
const reader = new FileReader();
reader.onloadstart = ev => handleLoadStart(ev, file);
reader.onprogress = ev => handleProgress(ev, file);
reader.readAsArrayBuffer(file);
}
}
document
.querySelector("#files")
.addEventListener("change", handleFileSelect, false);
читать большие файлы
Для больших файлов обычно используется идея загрузки в несколько частей для решения проблемы. Как упоминалось в начале статьи, File — это частный случай Blob. И у Блоба естьметод среза, через который фронтенд может реализовать операцию чтения больших файлов в шардах.
Для удобства объяснения сначала подготовьте файл txt, содержимое файла:hello world.
Пример кода выглядит следующим образом.В коде читаются только первые 5 байтов.Поскольку каждая английская буква занимает 1 байт, результатом печати должно быть "hello".
function handleFileSelect(event) {
let { files } = event.target;
if (!files.length) {
return;
}
// 为了方便说明,这里仅仅读取第一个文件
const file = files[0];
// 读取前5个字节的内容
const blob = file.slice(0, 5);
const reader = new FileReader();
// 控制台输出结果应该是:hello
reader.onload = ev => console.log(ev.target.result);
reader.readAsText(blob);
}
document
.querySelector("#files")
.addEventListener("change", handleFileSelect, false);
перетащить загрузить
Это точно так же, как File API, описанный ранее. Единственное, что требует специальной обработки, это то, что запись доступа к файловому объекту изменилась. для<input>Тег, прослушивание событий onchange, FileList хранится в event.target.files, для операций перетаскивания FileList хранится в параметре функции обратного вызова события перетаскивания, доступ к которому можно получить через event.dataTransfer.files.
Нужно изменить html-код:
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<style>
#container {
width: 300px;
height: 300px;
border: 3px dotted red;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="./script.js"></script>
</body>
</html>
Код файла сценария выглядит следующим образом:
function handleDropover(event) {
event.stopPropagation();
event.preventDefault();
}
function handleDrop(event) {
event.stopPropagation();
event.preventDefault();
/***** 访问拖拽文件 *****/
const files = event.dataTransfer.files;
console.log(files);
/**********/
}
const target = document.querySelector("#container");
target.addEventListener("dragover", handleDropover);
target.addEventListener("drop", handleDrop);
Связанный с серверной частью
Связанный с серверной частью выходит за рамки этой статьи, вы можете обратиться кэта статья.