把 input 的 type 设为 file 就是文件选择框,点击弹出系统选择器。multiple 允许选多个文件,accept 限制可接受的类型(accept=image/* 只显示图片)。上传必须配合 POST 与 enctype=multipart/form-data,这是协议层面的硬性要求,用 GET 或默认编码传不了文件内容。服务端拿到的文件名由后端框架处理。
纯 HTML 能做的有限,体验升级基本靠 JS:监听 change 事件拿到 files 列表,FileReader 可以本地预览图片再上传,FormData 配合 fetch 实现无刷新上传与进度条。安全上有两道闸必须装:前端 accept 与大小检查只是提示(可绕过),真正的校验必须在服务端做;上传按钮若无限制,攻击者可塞进来脚本伪装成图片的服务器文件。
<style> form.uf { border: 1px solid #4a9eff; border-radius: 8px; padding: 14px; } .uf label { font-size: 13px; } .uf input[type=file] { margin: 8px 0; } .uf button { padding: 6px 18px; border: none; border-radius: 6px; background: #4a9eff; color: #fff; cursor: pointer; } .prev { max-width: 120px; max-height: 90px; margin-top: 6px; border-radius: 6px; } </style> <form class="uf" action="/upload" method="post" enctype="multipart/form-data"> <label>头像(仅图片,可多选) <input type="file" name="avatar" accept="image/*" multiple onchange="const f=this.files[0];const img=document.getElementById('pv'); if(f){img.src=URL.createObjectURL(f);img.style.display='block';}"> </label> <img id="pv" class="prev" style="display:none" alt="选择后的预览"> <br> <button type="submit">上传</button> </form>