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

iOS端上传图片与JSON至后端时图片无法被接收的技术求助

上传图片与JSON到后端时后端无法获取图片的解决方案

问题根源

你的代码中处理图片二进制数据的逻辑存在错误:在ChamaDataField函数里,你将图片的二进制Data通过String(data: data, encoding: .utf8)转换为字符串,再转回Data。但图片的二进制内容并非合法的UTF-8编码文本,这个转换过程会导致数据丢失或损坏,最终后端接收到的图片数据是无效的,自然无法正确解析。

修复方案

重构图片字段的拼接逻辑,直接操作二进制数据,避免字符串转换带来的损坏:

修改后的代码

// 重构图片字段拼接函数,直接返回Data而非String
func chamaDataField(fieldName: String, fileName: String, data: Data, mimeType: String) -> Data {
    var body = Data()
    // 添加边界和头部信息
    body.append("--\(boundary)\r\n".data(using: .utf8)!)
    body.append("Content-Disposition: form-data; name=\"\(fieldName)\"; filename=\"\(fileName)\"\r\n".data(using: .utf8)!)
    body.append("Content-Type: \(mimeType)\r\n\r\n".data(using: .utf8)!)
    // 直接添加图片二进制数据,不做字符串转换
    body.append(data)
    body.append("\r\n".data(using: .utf8)!)
    return body
}

func chamaTextField(named name: String, value: String) -> Data {
    var fieldString = ""
    fieldString += "--\(boundary)\r\n"
    fieldString += "Content-Disposition: form-data; name=\"\(name)\"\r\n\r\n"
    fieldString += value
    fieldString += "\r\n"
    return Data(fieldString.utf8)
}

private func myFormDataCallTwo(requestBody model: chamaOfficialsPhotoUploadRequestTwo, documentName: String, documentData: UIImage?, _ completion: @escaping (Bool, String?) -> ()) {
    let baseUrl = "https://mbankingtest.postbank.co.ke:9193/"
    let endpointPath = "mchama/api/gateway/files"
    
    guard let url = URL(string: baseUrl + endpointPath) else {
        completion(false, "Invalid URL")
        return
    }
    
    var request = URLRequest(url: url)
    
    guard let sessionValue = AppConfig.AppStore["sessionId"] as? String else {
        print("Failed to retrieve session ID")
        completion(false, nil)
        return
    }

    request.setValue(sessionValue, forHTTPHeaderField: "session_id")
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
    request.httpMethod = "POST"
    
    var body = Data()
    
    guard let documentsData = documentData else {
        completion(false, "document data is nil")
        return
    }
    
    guard let imageData = documentsData.jpegData(compressionQuality: 0.7) else {
        completion(false, "Failed to convert UIImage to Data")
        return
    }
    guard let jsonData = try? JSONEncoder().encode(model) else {
        completion(false, "Failed to encode model to json")
        return
    }
    
    // 使用重构后的函数拼接图片字段
    body.append(chamaDataField(fieldName: "files", fileName: "\(documentName).jpg", data: imageData, mimeType: "image/jpeg"))
    
    let imageHex = imageData.prefix(20).map { String(format: "%02x", $0) }.joined()
    print("Image Data (first 20 bytes as hex): \(imageHex)")
    
    // 拼接JSON字段
    guard let jsonString = String(data: jsonData, encoding: .utf8) else {
        completion(false, "Failed to convert JSON data to string")
        return
    }
    body.append(chamaTextField(named: "data", value: jsonString))
    
    // 闭合表单
    body.append("--\(boundary)--\r\n".data(using: .utf8)!)
    
    // Debug: Print JSON data
    print("JSON being sent: \(jsonString)")
    
    // Debug: Print final assembled body in chunks
    let bodyStringComponents = [
        String(data: body.prefix(100), encoding: .utf8) ?? "",
        "..."
    ]
    print("Request body: \(bodyStringComponents.joined())")
    
    request.httpBody = body
    
    for (key, value) in request.allHTTPHeaderFields ?? [:] {
        print("My Header - \(key) : \(value)")
    }
    
    if let bodyString = String(data: body, encoding: .utf8) {
        print("Request body: \(bodyString)")
    }
    
    let session = URLSession.shared
    session.dataTask(with: request) {(data, response, error) in
        if let error = error {
            completion(false, error.localizedDescription)
            return
        }
        
        if let response = response {
            print("Response: \(response)")
        }
        
        if let data = data {
            do {
                let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
                if let dataValue = jsonObject?["data"] as? String {
                    print("Document was uploaded successfully. identifier: \(dataValue)")
                    completion(true, dataValue)
                } else {
                    print("Document uploaded successfully but failed to parse response")
                    completion(true, nil)
                }
            } catch {
                print("Error decoding JSON response: \(error)")
                completion(false, error.localizedDescription)
            }
        } else {
            completion(false, "No response data received")
        }
    }.resume()
}

额外说明

  • 确保boundary是一个唯一的随机字符串,比如用UUID().uuidString生成,避免和请求内容中的字符串冲突
  • 修复后,图片的二进制数据会完整传递到后端,后端就能正确解析出图片文件
  • 完善了错误处理逻辑,在JSON转字符串失败时直接返回错误,避免强制解包崩溃

内容的提问来源于stack exchange,提问作者Collins Muthomi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 04:34:58