Swift中Multipart接口响应极慢问题排查求助
问题排查:Swift中Multipart接口请求极慢但Postman正常
我的网络状态正常,使用Postman请求目标接口时响应很快,但在Swift代码中调用同一个接口却需要5分钟才返回结果。尝试过多种优化手段仍未解决问题,以下是Multipart请求的封装代码及调用代码,恳请帮忙排查问题根源。
封装代码
class APINetworkManagerMultipart: NSObject { static let sharedInstance = APINetworkManagerMultipart() fileprivate override init() { super.init() } func serviceCallWithMultipartFormData<T: Codable>( url: URL, headers: [String: String]?, parameters: [String: Any], completion: @escaping (Result<T, Error>) -> Void ) { var request = URLRequest(url: url) request.httpMethod = "POST" let token = "Bearer mytoken" request.setValue(token, forHTTPHeaderField: "Authorization") let boundary = "Boundary-\(UUID().uuidString)" request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") let body = NSMutableData() for (key, value) in parameters { if let stringValue = value as? String { body.append("--\(boundary)\r\n".data(using: .utf8)!) body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: .utf8)!) body.append("\(stringValue)\r\n".data(using: .utf8)!) } else if let data = value as? Data { body.append("--\(boundary)\r\n".data(using: .utf8)!) body.append("Content-Disposition: form-data; name=\"\(key)\"; filename=\"file\"\r\n".data(using: .utf8)!) body.append("Content-Type: application/octet-stream\r\n\r\n".data(using: .utf8)!) body.append(data) body.append("\r\n".data(using: .utf8)!) } } body.append("--\(boundary)--\r\n".data(using: .utf8)!) request.httpBody = body as Data if let customHeaders = headers { for (key, value) in customHeaders { request.setValue(value, forHTTPHeaderField: key) } } DispatchQueue.global(qos: .background).async { let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { completion(.failure(error)) return } guard let data = data else { completion(.failure(error!)) return } do { let decodedData = try JSONDecoder().decode(T.self, from: data) completion(.success(decodedData)) } catch { completion(.failure(error)) } } task.resume() } } }
调用代码
func genericFormdataCall(){ let urlStr = URL(string: "https://prg-name/dev/api/student/edit-profile")! let parameters: [String: Any] = [ "dob": "2005-07-24", "name": "Student", "gender": "M", "school_location": "TestLocation", "school_name": "K V", "grade": "12th grade", "student_bio": "I am a student", "profile_pic": nil ] as! [String : Any] DispatchQueue.global().async { APINetworkManagerMultipart.sharedInstance.serviceCallWithMultipartFormData(url: urlStr, headers: nil, parameters: parameters) { (result: Result<MultipartModel, Error>) in switch result { case .success(let response): // Handle the successful response self.formdataResponse = response print("Response: \(response)") case .failure(let error): // Handle the error print("Error: \(error)") } } } }
问题分析及修复建议
1. 参数中nil值未处理导致请求格式异常
调用代码里的profile_pic参数为nil,但封装代码没有处理nil的逻辑,直接跳过该参数。而Postman会自动忽略空值或按服务器预期的格式传递空字段,服务器端可能因缺少该参数或解析异常,一直处于等待状态导致超时。
- 修复方案:
- 移除参数中的
nil键值对; - 或在封装代码中添加
nil处理逻辑,比如传递空字符串:else if value is NSNull || value == nil { body.append("--\(boundary)\r\n".data(using: .utf8)!) body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: .utf8)!) body.append("\r\n".data(using: .utf8)!) }
- 移除参数中的
2. 手动拼接Multipart格式易出错
手动构建Multipart请求体容易出现换行符、边界符拼接错误,服务器端解析时卡住。建议使用URLSession原生的MultipartFormData类构建请求体,避免格式错误。
3. 不必要的线程嵌套
封装代码已在后台队列执行dataTask,调用代码又额外嵌套了一层DispatchQueue.global().async,会增加线程调度开销,建议去掉外层异步调用。
4. 添加合理的请求超时设置
默认URLRequest超时时间较长,可手动设置合理超时,避免长时间无意义等待:
var request = URLRequest(url: url) request.timeoutInterval = 30 // 设置30秒超时
内容的提问来源于stack exchange,提问作者Swift
相关产品推荐
相关产品推荐

