Swift5+PHP本地服务器图片上传故障排查求助
Swift5 + PHP 本地服务器图片上传调试求助
我用Swift5(Xcode版本12.5.1)和PHP向本地服务器上传图片,下载示例修改后仅文件夹创建功能正常,图片上传失败。以下是修改后的代码及错误信息:
Swift客户端代码
import UIKit class ViewController: UIViewController, UIImagePickerControllerDelegate,UINavigationControllerDelegate { @IBOutlet weak var myActivityIndicator: UIActivityIndicatorView! @IBOutlet weak var myImageView: UIImageView! @IBAction func uploadButtonTapped(_ sender: Any) { myImageUploadRequest() } @IBAction func selectPhotoButtonTapped(_ sender: Any) { let myPickerController = UIImagePickerController() myPickerController.delegate = self; myPickerController.sourceType = UIImagePickerController.SourceType.photoLibrary self.present(myPickerController, animated: true, completion: nil) } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { myImageView.image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage myImageView.backgroundColor = UIColor.clear self.dismiss(animated: true, completion: nil) } override func viewDidLoad() { super.viewDidLoad() } func generateBoundaryString() -> String { return "Boundary-\(UUID().uuidString)" } func myImageUploadRequest() { let myUrl = NSURL(string: "http://localhost/~*******/PHP/App/scripts/imageUpload.php"); let request = NSMutableURLRequest(url:myUrl! as URL); request.httpMethod = "POST"; let param = [ "firstName" : "Sergey", "lastName" : "Kargopolov", "userId" : "9" ] let boundary = generateBoundaryString() request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") let imageData = myImageView.image!.jpegData(compressionQuality: 1) if(imageData==nil) { return; } print("imageData =\(imageData as Any)") request.httpBody = createBodyWithParameters(parameters: param, filePathKey: "file", imageDataKey: imageData! as NSData, boundary: boundary) as Data myActivityIndicator.startAnimating(); let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in if error != nil { print("error=\(String(describing: error))") return } print("******* response = \(String(describing: response))") let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue) print("****** response data = \(responseString!)") do { let json = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary print(json as Any) DispatchQueue.main.async { self.myActivityIndicator.stopAnimating() self.myImageView.image = nil; } }catch { print(error) } } task.resume() } func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: NSData, boundary: String) -> NSData { let body = NSMutableData(); if parameters != nil { for (key, value) in parameters! { body.appendString(string: "--\(boundary)\r\n") body.appendString(string: "Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n") body.appendString(string: "\(value)\r\n") } } let filename = "user-profile.jpg" let mimetype = "image/jpg" body.appendString(string: "--\(boundary)\r\n") body.appendString(string: "Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n") body.appendString(string: "Content-Type: \(mimetype)\r\n\r\n") body.append(imageDataKey as Data) body.appendString(string: "\r\n") return body } } extension NSMutableData { func appendString(string: String) { let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true) append(data!) } }
错误信息
imageData =Optional(2322803 bytes) 2022-12-12 04:50:44.756347+0300 ImageUploadExample[7201:311148] [] nw_protocol_get_quic_image_block_invoke dlopen libquic failed ******* response = Optional(<NSHTTPURLResponse: 0x6000031e55a0> { URL: http://localhost/~*******/PHP/App/scripts/imageUpload.php } { Status Code: 200, Headers { Connection = ( "Keep-Alive" ); "Content-Type" = ( "text/html; charset=UTF-8" ); Date = ( "Mon, 12 Dec 2022 01:50:44 GMT" ); "Keep-Alive" = ( "timeout=5, max=100" ); Server = ( "Apache/2.4.48 (Unix) PHP/8.1.13" ); "Transfer-Encoding" = ( Identity ); "X-Powered-By" = ( "PHP/8.1.13" ); } }) ****** response data = {"Message":"Sorry, there was an error uploading your file.","Status":"Error","userId":"9"} Optional({ Message = "Sorry, there was an error uploading your file."; Status = Error; userId = 9; })
排查及修复方案
1. Swift端:补全多部分请求的结束边界
当前createBodyWithParameters方法未添加结束边界,PHP无法正确解析完整的表单数据。修改该方法最后部分:
// 在return body前添加这一行 body.appendString(string: "--\(boundary)--\r\n") return body
2. PHP端:排查上传核心问题
既然文件夹能正常创建,重点检查以下几点:
- 目录权限:确保上传目录拥有写入权限,临时设置
777测试,生产环境改回755 - PHP配置限制:打开
php.ini检查:upload_max_filesize:设置为大于你上传的图片大小(比如10M)post_max_size:需大于upload_max_filesize(比如12M)max_execution_time:适当延长避免超时
- 打印PHP错误:在
imageUpload.php开头添加代码,直接查看具体错误:
error_reporting(E_ALL); ini_set('display_errors', 1);
3. Swift代码优化(可选)
- 避免强制解包,改用可选绑定:
guard let image = myImageView.image, let imageData = image.jpegData(compressionQuality: 0.8) else { print("图片为空或转换失败") return }
- 替换旧API为Swift原生类型:
guard let myUrl = URL(string: "http://localhost/~*******/PHP/App/scripts/imageUpload.php") else { print("URL格式错误") return } var request = URLRequest(url: myUrl) request.httpMethod = "POST"
4. 关于QUIC警告的说明
nw_protocol_get_quic_image_block_invoke dlopen libquic failed是系统级警告,和图片上传失败无关,可以忽略。
内容的提问来源于stack exchange,提问作者Alshaman
相关产品推荐
相关产品推荐

