一、文件选择交互
1. 多文件选择
html
<input type="file" multiple>
-
核心功能:支持同时选择多个文件
-
技术实现:
- 通过
$0.files
获取伪数组 file对象 - 遍历文件对象:
Array.from(files).forEach(file => ...)
- 通过
-
注意事项:
- 建议添加文件类型过滤(如
accept="image/*,application/pdf"
)防止用户上传不必要或者不被允许的文件类型 - 文件大小限制需在前端 / 后端同时验证
-
两端验证的作用
-
前端验证:主要是为了提升用户体验。在用户选择文件时,前端就可以快速检测文件大小是否超出限制,并及时给出提示,避免用户等待长时间上传后才被告知文件过大。
-
后端验证:前端验证可被绕过,所以后端验证是保障系统安全和稳定的最后一道防线。后端可以防止恶意用户绕过前端限制上传超大文件,避免对服务器资源造成过度占用。
-
- 建议添加文件类型过滤(如
2. 文件夹选择
html
<!-- chrome 火狐 opera 浏览器 -->
<input type="file" webkitdirectory mozdirectory odirectory>
-
核心功能:支持选择整个文件夹(需 Chrome 火狐 opera浏览器)
-
兼容性:
- 仅 Chrome/Firefox/Opera 支持
二、拖拽交互
1. 拖拽文件 / 文件夹
-
技术实现:
-
通过 每个
DataTransferItem 实例 对象上的 webkitGetAsEntry()
获取文件系统入口 -
递归遍历文件夹:
javascript
container.ondragenter = (e) => e.preventDefault();
container.ondragover = (e) => e.preventDefault();
container.ondrop = (e) => {
e.preventDefault();
const files = e.dataTransfer.items;
Array.from(files).forEach(file => {
const entry = file.webkitGetAsEntry();
if (entry.isDirectory) traverseDirectory(entry);
else if (entry.isFile) entry.file(processFile);
});
};
javascript
function traverseDirectory(entry) {
const reader = entry.createReader();
reader.readEntries(entries => {
entries.forEach(entry => {
if (entry.isDirectory) traverseDirectory(entry);
else if (entry.isFile) entry.file(file => processFile(file));
});
});
}
三、切片上传核心原理与代码结构
代码解析实现大文件切片上传的核心逻辑,重点包括:
- 文件切片算法
- 并发上传控制
- 基于 FormData 的 HTTP 传输
html
<script>
// 核心变量声明
let file = {};
let chunkList = [];
const MAX_CHUNK_SIZE = 2 * 1024 * 1024; // 2MB切片大小
</script>
(一)、文件切片处理
- 切片生成逻辑
javascript
function createChunk(f, size = MAX_CHUNK_SIZE) {
let cur = 0;
while (cur < f.size) {
chunkList.push({
file: f.slice(cur, cur + size),
});
cur += size;
}
}
-
使用 Blob.slice () 方法进行二进制切片
Blob
(Binary Large Object)即二进制大对象,它是 JavaScript 中用于表示不可变的、原始数据的对象。Blob
对象可以包含多种类型的数据,例如文本、图像、音频、视频等,它通常用于处理二进制数据,比如文件上传、下载、处理图像等场景。Blob
对象有以下特点:- 不可变性 :一旦创建,
Blob
对象的内容就不能被修改。 - 可以切片 :
Blob
对象提供了slice()
方法,允许你从一个Blob
对象中提取出一部分数据,形成一个新的Blob
对象。 - 可以用于文件操作 :在文件上传时,
File
对象实际上是Blob
对象的一个子类,因此File
对象继承了Blob
的所有属性和方法。 f
是一个File
对象(因为File
是Blob
的子类,所以可以调用Blob
的方法),f.slice(cur, cur + size)
就是在调用Blob
的slice()
方法来对文件进行切片操作。
-
循环处理直至整个文件分割完毕
-
每个切片包含原始文件引用和分块索引
- 切片元数据封装
javascript
const uploadList = chunkList.map(({file:blobfile},index) => ({
file: blobfile,
chunkName: `${file.name}-${index}`,
fileName: file.name,
index
}));
(二)、并发上传控制
- 请求构建
javascript
const requsetList = list.map(({file,fileName,index,chunkName}) => {
const formData = new FormData();
formData.append('file', file);
formData.append('fileName', fileName);
formData.append('index', index);
formData.append('chunkName', chunkName);
return axios({
method: 'post',
url: 'http://localhost:3000/upload',
data: formData,
});
});
- 并发执行
javascript
await Promise.all(requsetList)
console.log('所有切片上传完成');
- 使用 Promise.all 实现并发控制
- 建议生产环境增加并发数限制(如 5 个同时上传)
- 需配合后端实现切片合并逻辑
如果您觉得这篇文章对您有帮助,欢迎点赞和收藏,大家的支持是我继续创作优质内容的动力🌹🌹🌹也希望您能在😉😉😉我的主页 😉😉😉找到更多对您有帮助的内容。
- 致敬每一位赶路人