XMLHttpRequest图片上传桌面端正常移动端失效,托管商升级系统后故障求助
问题排查方案
一、优先排查服务端配置变更(服务商升级导致的概率最高)
- 检查PHP上传相关配置:确认
upload_max_filesize、post_max_size、memory_limit三个参数的值是否被调小,移动端拍摄的照片通常体积远大于桌面端测试图片,很容易超出限制 - 检查
attachments目录权限:服务商升级系统可能重置了目录读写权限,确认该目录权限设置为755,所属用户与PHP运行用户一致 - 检查服务器端WAF/防火墙规则:升级后可能新增了移动端UA上传限制、无Referer的POST请求拦截、FormData上传校验规则变更等逻辑,可在upload.php最开头添加日志代码
file_put_contents('upload_log.txt', json_encode($_FILES).PHP_EOL.json_encode($_SERVER), FILE_APPEND);,验证移动端请求是否正常到达PHP脚本、是否正确获取到$_FILES数据 - 检查HTTPS配置:如果服务商升级后强制跳转HTTPS,但前端请求仍使用HTTP路径,部分移动端浏览器会直接拦截跨协议请求
二、代码缺陷排查
1. PHP端逻辑修复
现有后缀拆分逻辑存在缺陷:如果文件名包含多个点(如test.photo.jpg),explode后取索引1的位置拿到的是photo而非jpg,会导致后缀识别错误,部分移动端拍照生成的文件名带多个点就会上传失败,建议替换为pathinfo获取后缀,同时添加错误日志:
if (isset($_FILES['attachment'])) { $file_tmp = $_FILES['attachment']['tmp_name']; // 替换原有后缀获取逻辑 $file_ext = strtolower(pathinfo($_FILES['attachment']['name'], PATHINFO_EXTENSION)); $file_name_new = md5(uniqid().mt_rand()).".".$file_ext; $target = "attachments/" . $file_name_new; if(move_uploaded_file( $file_tmp, $target )){ echo "successful-{$file_name_new}"; }else{ // 记录移动文件失败的日志 file_put_contents('upload_error.txt', '移动文件失败:'.$target.PHP_EOL, FILE_APPEND); echo "error-move failed"; } }
2. 前端逻辑修复
- 部分移动端浏览器在
file控件被设为disabled后会自动清空选中的文件数据:你当前在fileSelected方法中提前把#attachment设为禁用,后续调用uploadFile时读取files[0]可能为空,建议将$("#attachment").prop('disabled', true);这行代码删除或移到xhr.send()之后 - 补充超时处理:部分移动端网络不稳定时请求会无限挂起,不会触发error事件,可在
xhr.open之后添加xhr.timeout = 30000;,同时绑定超时事件回调 - 增加返回值校验:在
uploadComplete中打印服务端返回的完整内容console.log(resp),可通过移动端远程调试查看返回值是否被服务商插入的广告、跳转代码污染,导致respArr[0]无法匹配successful
三、移动端特有兼容性排查
- 部分iOS Safari限制:如果页面运行在非HTTPS环境下,iOS 15及以上版本的Safari会限制不安全的POST上传;另外
capture="camera"属性在部分iOS版本中会导致文件选择异常,可先移除该属性测试 - 安卓定制浏览器兼容:部分国产浏览器会修改file控件的name属性或FormData结构,可在
xhr.send之前打印FormData内容,确认attachment字段是否正常存在
内容的提问来源于stack exchange,提问作者Shahrukh
相关产品推荐
相关产品推荐

