Swift 4.2结合PHP上传图片至服务器报错,请求排查问题
排查与修复你的图片上传问题
咱们一步步来拆解你遇到的问题——API返回错误的核心原因其实是图片文件名没有正确扩展名,再加上Swift代码里的参数传递小隐患,还有PHP端的错误处理漏洞,导致整个流程卡壳了。下面是具体的修复方案:
一、Swift代码的关键修复点
1. 图片文件名的错误
你现在用generateBoundaryString()作为图片的fileName,这个字符串是随机的无后缀内容,传到PHP端后,$image_name没有扩展名,直接触发了“Image extension is not Allowed!”的错误。
改成生成带.jpg后缀的唯一文件名就行,比如用UUID保证唯一性:
// 替换原来的fileName部分 let fileName = "\(UUID().uuidString).jpg" multipartFormData.append(imageToUpload.jpegData(compressionQuality: 0.75)!, withName: "image", fileName: fileName, mimeType: "image/jpeg")
2. 参数传递的类型安全问题
原来的参数拼接用了(value as AnyObject).data(using: ...),这种强制转AnyObject的写法很容易出问题,换成更安全的String类型处理:
for (key, value) in params { guard let paramData = (value as? String)?.data(using: .utf8) else { print("Failed to convert parameter \(key) to data") continue } multipartFormData.append(paramData, withName: key) }
3. 进度指示器的冗余调用
你在上传进度闭包里又调用了showActivityIndicator(),这会重复显示指示器,改成只在上传开始前显示,进度闭包里打印进度值就好:
upload.uploadProgress(closure: { (progress) in print("Upload progress: \(progress.fractionCompleted * 100)%") })
二、PHP代码的漏洞修复
1. 错误逻辑的覆盖问题
原来的代码里,第一个if(empty(...))之后没加else,如果触发这个条件后,后面的扩展名检查还会执行,可能覆盖$result的内容。而且完全没处理数据库插入失败、文件移动失败的情况,改成链式判断+完整错误处理:
<?php include 'include/connect.php'; // 用空值合并避免未定义索引错误 $name = $_POST["name"] ?? ''; $age = $_POST["age"] ?? ''; $xName = mysqli_real_escape_string($conn, $name); $xAge = mysqli_real_escape_string($conn, $age); $result = array(); $uploads_dir = 'img'; // 先检查图片是否成功上传 if (!isset($_FILES["image"]) || $_FILES["image"]["error"] !== UPLOAD_ERR_OK) { $result["message"] = "No image uploaded or upload failed."; $result["status"] = "0"; $result["post"] = $_POST; $result["files"] = $_FILES; } else { $tmp_name = $_FILES["image"]["tmp_name"]; $image_name = basename($_FILES["image"]["name"]); $supported_image = array('gif','jpg','jpeg','png'); $ext = strtolower(pathinfo($image_name, PATHINFO_EXTENSION)); if(empty($xName) || empty($xAge)) { $result["message"] = "Please fill all required fields."; $result["status"] = "0"; $result["post"] = $_POST; $result["files"] = $_FILES; } elseif (!in_array($ext, $supported_image)) { $result["message"] = "Sorry, Image extension is not Allowed!"; $result["status"] = "0"; $result["post"] = $_POST; $result["files"] = $_FILES; } else { $query ="INSERT INTO images (name, age, image) VALUES ('$xName', '$xAge','$image_name')"; if (mysqli_query($conn, $query)) { // 确保上传目录存在,不存在就创建 if (!file_exists($uploads_dir)) { mkdir($uploads_dir, 0755, true); } // 处理文件移动失败的情况 if(move_uploaded_file($tmp_name,"$uploads_dir/$image_name")){ $result["message"] = "Data has been uploaded successfully."; $result["status"] = "1"; } else { $result["message"] = "Failed to save image file."; $result["status"] = "0"; // 文件保存失败,回滚数据库插入 mysqli_query($conn, "DELETE FROM images WHERE image = '$image_name'"); } $result["post"] = $_POST; $result["files"] = $_FILES; } else { // 返回数据库错误信息,方便调试 $result["message"] = "Database insertion failed: " . mysqli_error($conn); $result["status"] = "0"; $result["post"] = $_POST; $result["files"] = $_FILES; } } } echo json_encode($result); ?>
2. 增加上传目录检查
如果img目录不存在,move_uploaded_file会直接失败,所以代码里加了目录判断和创建的逻辑。
3. 完善错误场景处理
现在会处理数据库插入失败、文件移动失败的情况,还会返回具体的错误信息,方便你调试。
三、调试小技巧
- 在Swift的
upload.responseJSON里打印完整的response.result,能直接看到API返回的错误详情,帮你快速定位问题。 - 调试PHP时可以暂时开启错误提示:
error_reporting(E_ALL); ini_set('display_errors', 1);,能看到PHP的具体报错。
内容的提问来源于stack exchange,提问作者Ahmed
相关产品推荐
相关产品推荐

