You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 16:46:13