仅靠 input.files.length === 0 不能可靠判断“上传为空”,必须结合 file.size === 0 检查空文件;Go 中需用 file.Read() 验证是否真为空,PHP 则应检查 $_FILES"x" 而非 isset。

仅靠 input.files.length === 0 不能可靠判断“上传为空”——它只说明用户没选文件,但无法区分“未选择”和“选了空文件(0 字节)”。
前端:用 input.files 和 file.size 做初步筛选
用户点击上传前,你能在 change 事件里拿到 event.target.files。注意以下三点:
-
input.files.length === 0表示用户根本没点选,这是最常见“空上传”场景 - 若
length > 0,必须检查file.size === 0—— 这才是真正的空文件(比如新建一个 txt 文件不写内容就上传) - 务必在验证失败后执行
input.value = '',否则重复选同一空文件时change不再触发
后端:Go 中必须区分 http.ErrMissingFile 和空内容
Go 的 r.FormFile("name") 返回值不能直接告诉你“是不是空”,得靠错误类型 + 内容读取:
- 如果
err == http.ErrMissingFile:表单压根没提交该字段,等价于前端files.length === 0 - 如果
err == nil但header.Size == 0:仍不可信,因为header.Size来自请求头,可能被篡改或丢失 - 唯一可靠方式是打开
file并调用file.Read()一次,检查是否返回io.EOF或0字节
PHP 中要查 $_FILES["x"]["error"] 而非是否存在数组键
很多人误用 isset($_FILES["x"]) 判断,但 PHP 即使用户没选文件,$_FILES["x"] 依然存在,只是 error 值为 UPLOAD_ERR_NO_FILE(值为 4):
立即学习“前端免费学习笔记(深入)”;
-
$_FILES["x"]["error"] === UPLOAD_ERR_OK(0):文件正常上传,可继续 -
$_FILES["x"]["error"] === UPLOAD_ERR_NO_FILE(4):用户未选择文件 -
$_FILES["x"]["error"] === UPLOAD_ERR_OK且$_FILES["x"]["size"] === 0:已上传但内容为空 —— 此时才需进一步读取验证
真正容易被忽略的是:**空文件(0 字节)和未选择文件,在语义、调试路径、用户提示上必须分开处理**。前者可能是用户误操作,后者大概率是交互流程断点;而服务端如果不做 Read() 校验,就永远不知道客户端传了个“合法但无内容”的文件。



















