安卓上传视频到服务器失败,核心排查思路是先分清是网络问题、文件问题还是服务器接口问题,按日志定位错误码,再针对性处理,绝大多数情况都能自己解决。
大多数视频传不上去,卡在第一步:日志里藏着真相
很多朋友一遇到上传失败就慌,其实安卓端上传视频失败,90%以上不是代码写错了,而是文件太大、超时太短、权限没给全这三件事,与其瞎猜,不如先把日志拉出来看。
操作路径:Android Studio → Logcat → 过滤关键字
Upload或Http,重点看SocketTimeoutException、FileNotFoundException、Permission Denied这三个异常。
我在帮别人排查上传问题的时候,发现一个规律:凡是超过100MB的视频,默认超时时间基本都不够用,Wi-Fi环境下传100MB视频,普遍需要30到60秒,如果你代码里设置的 connectTimeout 和 readTimeout 还是默认的10秒,那必挂无疑。
除了超时,服务端返回的错误码也是关键线索。413 Request Entity Too Large 表示服务器限制了请求体大小,401 Unauthorized 是鉴权失效,500 Internal Server Error 就纯属后端接口挂了,遇到不同错误码,解决方向完全不一样:
413→ 改服务器Nginx或Tomcat的上传大小限制401→ 检查token是否过期,重新登录获取凭证500→ 把完整堆栈发给后端同事,多半是接口没做分片处理SocketTimeoutException→ 全局搜索代码里的超时设置,改大再说
视频上传服务器失败原因分析,从三个层面逐个击破
第一层:网络环境比代码更不可控
安卓手机的上传体验,和iOS最大的区别在于网络切换太频繁,从Wi-Fi跳到4G/5G,或者地铁里信号弱,TCP连接分分钟断给你看,这不是你代码的锅,但你可以用代码去适应它。
行业共识认为,移动端上传视频必须做断点续传,具体做法是把视频文件按2MB到5MB大小切成多个分片,每个分片独立上传,失败的分片单独重试,全部传完再让服务端合并,这样就算断网10次,也只是重传最后那一片而已。
另一个容易踩的坑是DNS解析失败,有些安卓机型在弱网环境下,解析你的OSS或CDN域名会偶发性失败,解决办法是给OkHttp或Retrofit配置多个备用域名,或者直接用IP加Host头的方式绕过DNS,不过这招有风险,只建议在紧急线上问题排查时用。
第二层:文件本身和权限问题被严重低估
很多人检查了网络,检查了代码,结果发现是文件读取权限没搞定,安卓6.0以上需要动态申请 READ_EXTERNAL_STORAGE,安卓10以上推荐用 MediaStore 或 SAF 文件选择器,直接拿不到文件路径是常态。
我见过一个案例,明明上传接口没问题,但一直报 FileNotFoundException,最后发现是用了 getExternalStorageDirectory() 去读安卓11的公共目录必崩无疑,后来改成用 Uri 配合 ContentResolver 打开输入流,问题瞬间解决。
视频编码格式也可能导致上传后无法播放,大部分手机拍出来的视频是H.264编码,但如果用户从某些特殊App保存视频,可能是H.265或VP9编码,服务端如果不支持转码,就会出现“上传成功但播放失败”的假象,这种情况不算上传失败,但用户体验比上传失败还糟糕。
第三层:服务端配置和接口设计要背一半的锅
安卓端改得再完美,服务端不配合也是白搭,最常见的问题是默认请求体大小限制,Tomcat默认 maxPostSize 是2MB,Nginx默认 client_max_body_size 是1MB,不调大这两个值,视频传一个挂一个。
还有接口设计问题,有些后端接口要求一次性传完整文件,不支持分片合流,当你辛辛苦苦写完分片上传逻辑,结果服务端根本没有对应的合并接口,这时候就得和后端商量,把接口改成支持分片,别不好意思,这不是你这边能单独解决的事。
安卓视频上传超时怎么解决,直接抄这几组配置
超时问题值得单独拿出来说,因为它是出现频率最高的上传失败原因,而且改起来最快。
拿OkHttp举例,默认的 connectTimeout 是10秒,readTimeout 是10秒,writeTimeout 是10秒,上传100MB视频,就算Wi-Fi速度能跑满5MB/s,也需要20秒,这还没算服务器处理时间,所以必须重写这几个值,没有讨价还价的余地。
推荐配置:
connectTimeout(30, TimeUnit.SECONDS)+readTimeout(60, TimeUnit.SECONDS)+writeTimeout(60, TimeUnit.SECONDS)起步,如果视频经常超过500MB,建议直接把readTimeout拉到120秒。
Retrofit的 @Multipart 上传也一样,超时配置跟着OkHttp的 OkHttpClient 走,改一个地方全局生效。
如果上传过程中进度条卡住不动,但没过一会又突然成功,这种是典型的
readTimeout 太短,因为服务器在合并分片期间不会返回数据,客户端一直在等,等不到就报超时,但实际上服务器还在处理,把 readTimeout 调大,这类问题立刻消失。
安卓本地视频上传失败排查指南,分场景对照处理
小视频能传,大视频必失败
这几乎可以断定是服务端限制请求体大小,或者客户端超时设置太短,先看服务器报错日志,如果是 413 错误,去调Nginx的 client_max_body_size,改成 100m 或 200m,重启Nginx再测,如果是客户端报 SocketTimeoutException,那就照上面说的把超时时间改大。
传一半断掉,重试还是断
这是弱网下的经典问题,解决办法就一个字:切。
- 检测Wi-Fi信号强度低于某个阈值时,自动提示用户切换网络
- 上传开始前先ping一下服务器IP,延迟高于200ms就给出降级提示
- 使用分片上传策略,单片失败最多重试3次,单片超时时间设为30秒
- 重试退避策略用指数退避,第一次等1秒,第二次2秒,第三次4秒,避免雪崩
视频传完了,服务器说文件损坏
问题多半出在压缩和编码环节,有些开发者为了减小体积,在本地用MediaCodec重新编码了视频,但编码参数设置错误,导致输出文件不完整,业内专家指出,这类问题在视频压缩环节最常见,建议先关闭压缩直接传原文件,如果能成功,再逐步排查压缩代码的逻辑。
Multipart的Content-Type也要注意,传视频文件时,MediaType 应设为 video/mp4 或对应的实际格式,不能统一用 application/octet-stream,否则某些服务端框架会解析异常。
用好工具和日志定位,五分钟锁定病根
不会看日志的安卓开发,排查上传问题就像盲人摸象,推荐三个实用工具,都是免费的:
- Stetho:FaceBook出品,直接在Chrome里查看网络请求详情和响应头,上传失败是哪个环节报错一目了然
- Charles:抓包工具,安卓手机配好代理后能看到完整的HTTPS请求和响应体,尤其是服务器的错误信息,很多藏在响应体里
- adb logcat:系统级别的日志输出,如果遇到NDK层面的崩溃或系统权限拦截,只能靠它来抓
排查步骤按这个顺序走:
- 抓包看请求是否发出,响应码是多少
- 看服务端日志,确认请求是否到达
- 检查服务器上视频文件大小和本地原文件大小是否一致
- 如果文件大小一致,下载下来用播放器打开验证完整性
- 如果文件不一致,检查分片上传逻辑里的偏移量计算是否正确
这套流程走完,绝大多数问题都能定位到具体环节,不会再出现“前端说传完了,后端说没收到”的扯皮局面。
安卓视频上传失败定位方法,从报错信息反向推导
很多上传失败其实是可以从报错信息直接读出原因的,我不会建议你去百度搜大段教程浪费时间,按下面的对应关系直接排查就行:
| 报错信息 | 根本原因 | 处理方向 |
|---|---|---|
Connection refused |
服务器端口未开或防火墙拦截 | 检查服务器安全组和防火墙策略 |
SSLHandshakeException |
HTTPS证书过期或不受信任 | 更新证书,或配置OkHttp信任证书 |
No space left on device |
服务器磁盘满了 | 清理服务器临时目录或扩容磁盘 |
Broken pipe |
客户端写入时连接被服务端断开 | 检查服务端是否主动关闭了空闲连接 |
MalformedInputException |
文件名或路径含非法字符 | 对文件名做URLEncoder编码处理 |
最后补充一点心态层面的建议,安卓视频上传本来就是一个链路很长的操作,涉及的环节包括权限申请、文件读取、网络传输、服务端存储、转码播放,任何一环出问题都会表现为“上传失败”,遇到问题不要慌,按照日志定位、网络排查、服务端验证的顺序来,就能快速找到突破口。
常见问题速问速答
上传视频时总是进度到100%后报超时,是什么原因?
这是 readTimeout 设置过短导致的,视频数据其实已经传完了,但服务器还在处理文件(比如写入磁盘或生成缩略图),客户端等不到响应就断开了连接,把 readTimeout 设置为60秒以上,或者改成流式读取响应,一般就能解决。
安卓10及以上系统读取视频文件权限被拒绝怎么处理?
不要直接使用文件路径方式读取公共目录,改用 ActivityResultContracts.GetContent() 或 OpenDocument 让用户选择视频,通过 ContentResolver.openInputStream(uri) 获取文件流进行上传,同时记得在AndroidManifest中声明 READ_EXTERNAL_STORAGE 权限,并针对Android 13及以上版本适配 READ_MEDIA_VIDEO 权限。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/747967.html





