典型现象:wx.chooseImage / wx.chooseMedia 能选出本地图,一点上传就失败。控制台常见 uploadFile:fail、url not in domain list、ssl hand shake error,或 success 回调里 statusCode 不是 200。选图正常、预览正常,问题几乎都在「上传通道」而不是业务表单本身。
下面按「先读完整 errMsg → 再核对 uploadFile 合法域名 → 再核 filePath → 再核 HTTPS/证书 → 再看服务端响应」走。每一步都能在开发者工具或后台核对。
0. 先分清失败发生在哪一层
wx.uploadFile 失败至少有三层,处理路径不同:
- 客户端直接 fail:域名未配置、非法 URL、临时文件失效、网络中断;
- 请求发出去了,但 TLS/证书握手失败:HTTPS 证书链、SNI、中间人代理;
- HTTP 层有响应,但业务失败 :
statusCode4xx/5xx,或 body 里业务码非成功。
先在 fail 回调里把完整 errMsg 打出来,不要只弹「上传失败」。再在 success 里始终打印 statusCode 与 data 前几百字符------很多「上传失败」其实是服务端 413/401,客户端却进了 success。
javascript
wx.uploadFile({
url: 'https://api.example.com/upload',
filePath: tempFilePath,
name: 'file',
formData: { biz: 'avatar' },
success(res) {
console.log('statusCode', res.statusCode, 'data', res.data);
},
fail(err) {
console.error('uploadFile fail', err);
}
});
1. uploadFile 合法域名必须单独配
小程序后台 开发 → 开发管理 → 开发设置 → 服务器域名 里,request 合法域名和 uploadFile 合法域名是两套。只配了 request、没配 uploadFile,真机上传必挂。
核对清单:
- 打开后台,确认上传接口的 主机名 (不含 path)已写入 uploadFile 合法域名;
- 协议必须是
https://,且与代码里的url主机名完全一致(含是否带www); - 改完域名后,开发者工具点 详情 → 域名信息 刷新,或重新编译;真机需重新预览/体验版;
- 本地调试若勾了「不校验合法域名」,真机/体验版不会自动放行------以真机结果为准。
常见坑:把完整 path 写进域名列表(应只写主机)、把 IP 当域名、把测试环境域名留在正式版未同步。
2. 临时路径有时效:选完立刻传
chooseImage / chooseMedia 返回的 tempFilePaths / tempFiles[].tempFilePath 是本地临时文件,不是永久 URL。
- 选完立刻
uploadFile,不要先setData存几天再传; - 页面卸载、热重载、长时间停留后再传,临时文件可能已失效,表现为
file not found类 fail; - 需要二次使用时,先上传拿到服务端 URL,业务层只存远端地址;
- 多图上传用队列串行或有限并发,避免同一
tempFilePath被并发读导致偶发失败。
验证:fail 时把 filePath 打日志,确认不是空字符串、不是远端 http 地址、也不是过期后的旧 path。
3. URL、name、header 与 formData
接口约定不对时,客户端可能「看起来成功」但服务端没收文件:
url必须是完整 HTTPS 地址;name要与服务端表单字段名一致(常见是file/upload);改错字段名时,部分框架返回 200 + 业务错误;- 需要鉴权时把 token 放进
header(如Authorization),不要塞进文件名; formData只放字符串键值;不要把对象/数组直接塞进去而不序列化;- 不要手动设
Content-Type: multipart/form-data且自拼 boundary------让运行时生成。
4. HTTPS 证书与握手
ssl hand shake error / ERR_CERT_* 类错误,按下面查:
- 浏览器或
openssl s_client -connect host:443 -servername host看证书是否过期、链是否完整; - 证书域名是否覆盖你实际请求的主机(含多域名证书的 SAN);
- 服务器是否只开了 TLS1.0/过时套件------以微信客户端当前要求为准;
- 公司代理/抓包工具若在开发机中间人,开发者工具可能偶发过、真机不过;真机请关代理再试。
证书修好后,先用同一 URL 在手机浏览器打开确认可访问,再回小程序上传。
5. 服务端 statusCode 与体积限制
客户端进了 success 仍可能业务失败:
| 现象 | 优先查 |
|---|---|
| statusCode 401/403 | 鉴权 header、登录态过期 |
| statusCode 404 | 上传 path 写错、网关路由 |
| statusCode 413 | Nginx client_max_body_size、网关 body 限制 |
| statusCode 500 | 服务端落盘权限、对象存储密钥 |
| data 非 JSON / 业务码失败 | 字段名 name、文件类型白名单 |
图片过大时:上传前用 wx.compressImage 或自有压缩,再传;同时把服务端与网关的 body 上限对齐(例如都 ≥ 5MB),避免「工具里小图过、真机大图 413」。
6. 最小复现核对表
按顺序勾:
- 后台 uploadFile 合法域名 是否含该主机;
- 真机是否仍勾着仅开发工具生效的「不校验合法域名」错觉;
filePath是否为本次选择返回的临时路径;url是否 HTTPS 且主机与白名单一致;- success 里
statusCode是否 200,data业务是否成功; - 同 URL 用 curl/
Postmanmultipart 能否上传成功(隔离小程序与服务端问题)。
每改一轮:清缓存 → 重新编译 → 真机预览再传一张。用日志里的 errMsg / statusCode 验证,不要凭感觉连点重试。
本文由 DEVDIY 整理。我们日常主要做 WordPress / Shopify 外贸站与微信小程序的开发和线上排查,把这类上传失败问题拆成可复现步骤,方便自己和同行对照。
原文/延伸阅读:https://devdiy.cn/miniprogram/