Skip to content

最基本的文件上传

文件上传的起点不是“怎么发请求”,而是“怎么把用户选择的文件拿到前端代码里”。

最基本入口:input[type="file"]

浏览器里最基础的文件选择方式是:

html
<input type="file" id="fileInput" />

用户选择后,可以在 change 事件里拿到文件列表:

js
const fileInput = document.getElementById('fileInput')

fileInput.addEventListener('change', (event) => {
  const files = event.target.files
  console.log(files)
})

这里拿到的是 FileList,其中每一项通常都是 File 对象。

单文件和多文件

默认情况下通常是单文件选择。

如果需要多文件:

html
<input type="file" id="fileInput" multiple />

这时 files 里可能会有多个文件。

拿到文件后通常会做什么

最常见的后续步骤包括:

  • 展示文件名、大小、类型
  • 做前端校验
  • 组装成 FormData
  • 发起上传请求

所以“文件上传”一般可以拆成两段:

  1. 选择文件
  2. 发送文件

自定义上传按钮

原生文件输入框可用,但样式通常不够灵活,所以常见做法是隐藏原生控件,再用 label 触发选择:

html
<input type="file" id="fileInput" hidden />
<label for="fileInput" class="upload-btn">选择文件</label>
css
.upload-btn {
  display: inline-flex;
  padding: 6px 12px;
  border-radius: 6px;
  background: #1677ff;
  color: #fff;
  cursor: pointer;
}

这种方式的关键点是:

  • 不要丢掉原生输入框能力
  • 只是把触发入口换成更可控的 UI

拖拽上传

除了点击选择,还可以让用户把文件拖进页面区域。

html
<div id="dropZone">拖拽文件到此区域上传</div>
js
const dropZone = document.getElementById('dropZone')

dropZone.addEventListener('dragover', (event) => {
  event.preventDefault()
})

dropZone.addEventListener('drop', (event) => {
  event.preventDefault()
  const files = event.dataTransfer.files
  console.log(files)
})

这里最关键的是:

  • dragover 要阻止默认行为
  • drop 也要阻止默认行为

否则浏览器可能会直接打开文件,而不是交给页面处理。

拖拽上传适合什么

更适合:

  • 图片上传区
  • 附件管理面板
  • 桌面类操作感较强的页面

但它通常不是唯一入口,实际页面里常常会和点击选择并存。

使用时要注意什么

文件输入框的值不能随便模拟

出于安全原因,浏览器不会让脚本任意伪造本地文件路径。

只拿到文件不等于已经上传

File / FileList 只是前端拿到了文件对象,还没有发生网络传输。

校验通常要尽早做

常见校验包括:

  • 文件类型
  • 文件大小
  • 数量限制

这些通常在真正发送前就做。

使用建议

  • 最基础的文件上传入口优先从 input[type="file"] 理解。
  • 自定义样式时,优先保留原生输入框行为,而不是完全重造。
  • 拖拽上传适合作为增强入口,不一定适合作为唯一入口。
  • 把“选择文件”和“发送文件”分成两步理解,后续上传流程会更清晰。

基于 MIT 许可发布