HTML原生不支持上传文件夹结构,需用触发递归读取;敏感文件须前端按路径规则预筛并AES-GCM分片加密,IV/authTag等元数据独立Base64提交,服务端须白名单校验路径、隔离存储解密文件。

HTML 原生不支持直接上传整个文件夹的「目录结构」,但可通过 webkitdirectory 属性(Chrome/Edge/Firefox 支持)或 input[type="file"][webkitdirectory] 触发浏览器读取文件夹内所有文件;敏感文件加密必须在前端完成,且不能依赖后端补救——因为明文一旦离开用户设备,就已失控。
如何用 input 正确触发文件夹选择
关键不是“选中文件夹”,而是让浏览器递归读取其内容。原生 input 不支持 directory 标准属性(仅草案),必须用非标准但广泛支持的 webkitdirectory:
- 必须显式添加
webkitdirectory和directory两个属性,兼容性更稳: - 事件监听必须用
change,而非drop—— 拖拽文件夹时,DataTransfer.items在部分浏览器(如 Firefox)中会丢失子路径信息,webkitdirectoryinput 则保证files列表含完整相对路径(file.webkitRelativePath) -
files是FileList,不是数组,需转为数组才能用filter或map:Array.from(event.target.files) - 注意:Safari 完全不支持该特性,需降级提示用户手动压缩后上传
哪些文件算“敏感”?前端怎么标记并加密
不能靠扩展名硬判断(比如 .txt 里可能是密钥),也不能等全部文件读完再统一处理(内存爆炸)。合理做法是:按路径规则预筛 + 按需加密。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 定义敏感路径模式,例如:
/config/.*\.json$、/secrets/、.*\.env$—— 这些正则在匹配file.webkitRelativePath时执行 - 对命中规则的文件,使用
window.crypto.subtle.encrypt()执行 AES-GCM 加密,**必须**生成新iv(12 字节)、携带authTag,并把它们和密文一起塞进 FormData - 避免对大文件整块读取:
file.slice()分片 +FileReader.readAsArrayBuffer()逐片加密,边读边传,防止 OOM - 未命中的文件保持明文上传,但需在 FormData 中加字段标识:
is_encrypted: false,方便后端跳过解密逻辑
FormData 怎么组织加密文件和元数据
不能把 IV、salt、tag 拼进文件二进制头(破坏 MIME 类型,后端解析 multipart 会失败),必须作为独立字段提交:
- 密文本身用
Blob包装:new Blob([encryptedBuffer], {type: 'application/octet-stream'}) - IV、salt、authTag 全部 Base64 编码后作为字符串字段加入:
formData.append('iv', btoa(String.fromCharCode(...iv))) - 必须附带算法标识:
formData.append('cipher', 'AES-GCM-256'),否则后端无法确定如何解密 - 敏感文件原始名要保留(用于服务端还原路径),但需额外字段声明:
formData.append('original_name', file.webkitRelativePath) - 不要用
JSON.stringify()把所有元数据打包成一个字段——multipart 解析器不认嵌套 JSON,会当普通文本丢弃
容易被忽略的坑:路径还原与服务端信任边界
前端传来的 webkitRelativePath 是浏览器生成的,不可信;服务端收到加密文件后,绝不能直接按该路径写入磁盘。
- 服务端必须白名单校验路径层级(如最多允许 3 级子目录),并强制重写根目录:
path.join(UPLOAD_ROOT, 'upload_' + uuid(), sanitizePath(file.original_name)) - 解密失败时返回通用
400 Bad Request,禁止泄露"IV mismatch"或"invalid auth tag"等细节,防止侧信道攻击 - 加密只是传输保护,不是访问控制——解密后的临时文件必须存于非 Web 可达目录(如
/var/tmp/uploads/),且权限设为0o600,处理完立即fs.unlink() - 如果上传含符号链接或
../路径,webkitRelativePath可能被构造绕过,服务端必须做路径净化(path.resolve()+ 对比前缀)
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










