Laravel 5.1安卓端文件验证失败问题排查求助
结合你给出的请求头和问题现象,我大概率能定位到几个常见的原因——都是Laravel 5.1这类老版本处理移动端multipart请求时容易踩的坑:
1. PHP上传大小配置限制
看Android请求的content-length是3.4MB左右,而PC端只有23KB。Laravel依赖PHP的upload_max_filesize和post_max_size配置,如果这两个值设置得小于Android上传的文件大小,PHP会直接丢弃上传的文件,导致Laravel的验证器检测不到文件,自然验证失败。
解决方法:
修改服务器的php.ini文件:
upload_max_filesize = 8M post_max_size = 8M
修改后重启PHP服务,再测试Android端的上传。
2. Laravel 5.1对新型请求头的兼容问题
Android请求头里包含了sec-fetch-dest、sec-fetch-mode、sec-fetch-site这些较新的Fetch API相关头,而Laravel 5.1是2015年发布的版本,当时这些头还不存在,Symfony的HttpFoundation组件(Laravel依赖它处理请求)对这类头的解析可能存在异常,导致multipart请求的文件部分没被正确识别。
解决方法:
可以在App\Http\Middleware\VerifyCsrfToken或自定义中间件里,临时移除这些头再让请求进入Laravel处理流程:
public function handle($request, Closure $next) { // 移除可能干扰解析的新请求头 $request->headers->remove('sec-fetch-dest'); $request->headers->remove('sec-fetch-mode'); $request->headers->remove('sec-fetch-site'); return $next($request); }
3. Android WebKit的boundary格式异常
虽然请求头里的boundary看起来和PC端格式一致,但Android的Chrome在某些版本下,发送multipart请求时,请求体里的boundary前面会多出空格或其他不可见字符,导致Symfony无法正确识别分隔符,最终无法解析出上传的文件。
解决方法:
在Android端的上传代码里,手动指定boundary,确保请求头和请求体的boundary完全一致。比如在FormData构造后,手动提取生成的boundary并设置到请求头中。
4. 文件名字符编码问题
你的请求头显示accept-language包含俄语,Android端上传的文件名可能包含非ASCII字符,Laravel 5.1的默认字符集处理可能无法正确识别这类文件名,导致判定为无效文件。
解决方法:
在你的Request验证类里,添加验证前的钩子处理文件名编码:
public function rules() { return [ 'your_file_field' => 'file', ]; } // 验证前预处理文件信息 public function prepareForValidation() { if ($this->hasFile('your_file_field')) { $file = $this->file('your_file_field'); // 将文件名转码为UTF-8 $fileName = mb_convert_encoding($file->getClientOriginalName(), 'UTF-8', 'auto'); // 替换原始文件名的获取方法 $file->getClientOriginalName = fn() => $fileName; } }
建议先从第一个PHP配置的原因排查,这个是最常见且排查成本最低的。
内容的提问来源于stack exchange,提问作者devAston

