前言:功能点概括:1、多选文件 2、选择文件夹 3、拖拽 4、选择后形成一个列表,列表里有一些信息 5、有进度条 6、控制并发数 7、可取消 8、展示统计信息
1. 交互实现
交互的目标是要拿到 file 对象。只要拿到 file 对象,就能通过网络上传。
1.1 如何选择多文件
给 input 添加 multiple 属性
<input type="file" multiple />
1.2 如何选择文件夹
给 input 添加 webkitdirectory、mozddirectory、odirectory 属性
<input type="file" webkitdirectory mozddirectory odirectory />
1.3 如何拖拽文件及文件夹
使用拖拽 API 触发事件
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><metaname="viewport"content="initial-scale=1.0, user-scalable=no, width=device-width"/><title>document</title><style>.container {width: 100%;height: 200px;border: 1px solid;}</style></head><body><!-- 通过 $0.files 拿到所有文件File --><input type="file" multiple /><div class="container"></div><script>const div = document.querySelector(".container");// 都需要阻止默认行为,因为div是不允许任何东西拖拽到它上面的// 当进入时触发div.ondragenter = (e) => {console.log(1);e.preventDefault();};// 当有东西在盒子上时不断的触发div.ondragover = (e) => {console.log(2);e.preventDefault();};// 当有东西放在盒子上时触发div.ondrop = (e) => {e.preventDefault();const items = e.dataTransfer.items;for (const item of items) {const entry = item.webkitGetAsEntry();console.log(1, entry);if (entry.isFile) {// 处理文件:拿到File文件entry.file((file) => {console.log(2, file);});} else {const reader = entry.createReader();reader.readEntries((entries) => {console.log(entries);});}}};</script></body>
</html>
2. 网络
网络部分用 XHR(axios) / fetch。
2.1 如何实现多文件上传
有两种方案,一种是所有文件合并到一次请求里。另一种单文件上传,需要和后端协商。我们一般采取第二种,这样有文件上传失败,也不会影响其他文件的上传。方便做进度跟踪,大文件切片,控制并发上传数。
2.2 如何实现进度追踪
上传进度跟踪 fetch 是实现不了的。只能实现下载的进度跟踪。我们可以通过 xhr.upload.onprogress 来控制上传进度跟踪。
2.3 如何实现取消上传
XHR 通过 xhr.abort() 直接取消。fetch 是通过控制器 AbortController 取消