只有 type="file" 能触发原生文件选择框并生成 FileList 对象;其他 type 无法访问本地文件,且 value 只读、仅含文件名,须用 files 属性获取 File 对象。

file input 为什么选 type="file" 而不是其他 type
因为只有 type="file" 会触发浏览器原生文件选择对话框,并生成合法的 FileList 对象。用 type="text" 或 type="button" 都无法访问用户本地文件系统,这是浏览器安全策略强制限制的。
常见错误是试图用 JS 模拟点击隐藏的 input[type="file"] 后直接读取 value —— 实际上 value 只返回文件名(不含路径),且在多数浏览器中是只读的,不能赋值。真正可用的是 files 属性。
-
input.files是一个FileList,类似数组但不是 Array,需用[0]或Array.from()处理 - 单文件上传用
input.files[0];多文件需加multiple属性 - 不加
name属性会导致表单提交时该字段被忽略
如何监听文件选择并读取内容(非上传)
如果只是想预览或校验文件(比如读取图片 base64、检查 CSV 内容),不要立刻发请求,先用 FileReader 解析:
<input type="file" id="avatar">
<script>
const input = document.getElementById('avatar');
input.addEventListener('change', (e) => {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = () => {
console.log('base64:', reader.result); // 例如 data:image/png;base64,...
};
reader.readAsDataURL(file); // 或 readAsText(file, 'UTF-8')
});
</script>
注意:FileReader 是异步的,reader.result 在 onload 里才可用;若文件太大,readAsDataURL 会生成极长字符串,可能卡顿,此时建议用 readAsArrayBuffer 或分块处理。
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
立即学习“前端免费学习笔记(深入)”;
form 提交时 file input 的行为和坑
用 <form enctype="multipart/form-data"></form> 提交时,input[type="file"] 的 name 和选中的文件会作为 multipart body 的一部分发送。但有几个关键点容易出错:
- 必须显式设置
enctype="multipart/form-data",否则文件字段根本不会被发送(默认是application/x-www-form-urlencoded) - 服务端接收不到文件?先检查前端是否漏了
name,再确认后端框架是否启用了 multipart 解析(如 Express 需multer,Spring Boot 需spring.servlet.multipart.enabled=true) - 如果用 AJAX 提交,不能直接把
input.files[0]当作 JSON 发送 —— 必须用FormData包装
用 FormData 手动上传文件(推荐现代做法)
绕过表单 submit,用 fetch + FormData 更可控,也方便加进度条、取消、重试逻辑:
const form = new FormData();
form.append('avatar', input.files[0]); // key 名要和服务端约定一致
form.append('user_id', '123');
fetch('/api/upload', {
method: 'POST',
body: form // 不要设 Content-Type,浏览器会自动设为 multipart/form-data 并带上 boundary
}).then(r => r.json());
容易忽略的细节:FormData 的 append 第二个参数如果是 File 对象,它会自动带上文件名和类型;但如果传的是 Blob 或字符串,就得手动指定第三个参数(如 form.append('file', blob, 'custom.jpg'))。另外,fetch 不支持上传进度事件,要用 XMLHttpRequest.upload.onprogress 替代。


















