iOS:非Multipart方式上传大JSON文件的进度追踪问题
如何用Alamofire追踪JSON请求体的上传进度
当然可以实现!虽然Alamofire的常规JSON POST请求(比如直接传parameters的方式)不会暴露上传阶段的进度,但我们可以换个巧妙的思路绕过去——核心是先把包含base64图片的JSON序列化为Data,再用Alamofire的upload方法发送这个Data,这样既能保留JSON请求体的格式,又能利用uploadProgress闭包追踪上传进度。
具体步骤和代码示例
序列化JSON请求体并计算总字节数
首先把你的参数(包括base64编码的图片)转成JSON Data,这样我们能提前知道要上传的总数据大小,这是追踪进度的关键:// 假设你已经将UIImage转为base64字符串 let imageBase64 = "your-base64-image-string" let uploadParams: [String: Any] = [ "image": imageBase64, "userId": 123, "description": "A test image" ] // 序列化为JSON Data guard let jsonData = try? JSONSerialization.data(withJSONObject: uploadParams, options: []) else { print("JSON序列化失败") return } let totalUploadBytes = jsonData.count用Alamofire的
upload方法发送Data并追踪进度
用upload方法直接上传这个JSON Data,同时设置正确的Content-Type头(确保服务器识别为JSON请求),然后通过uploadProgress闭包获取实时进度:AF.upload(jsonData, to: "https://your-api-endpoint.com/upload") // 手动设置Content-Type为application/json,确保服务器正确解析 .setHeader(name: "Content-Type", value: "application/json") .validate() .uploadProgress { progress in // 这里获取实时上传进度 let progressPercentage = progress.fractionCompleted * 100 print("上传进度: \(String(format: "%.2f", progressPercentage))%") // 可以在这里更新UI,比如进度条的progress值 } .responseJSON { response in switch response.result { case .success(let responseData): print("上传成功,响应数据: \(responseData)") // 处理成功逻辑 case .failure(let error): print("上传失败,错误信息: \(error.localizedDescription)") // 处理错误逻辑 } }
为什么这个方案可行?
Alamofire的upload方法是专门为追踪上传进度设计的——不管你上传的是本地文件还是内存中的Data,它都会基于URLSession的任务进度回调,实时返回已发送字节数和总字节数。而我们提前序列化好JSON Data,就相当于把整个请求体变成了一个"虚拟文件"来上传,既满足了服务器对JSON请求体的要求,又能拿到上传进度。
注意事项
- 内存占用问题:base64编码后的图片会比原图片大33%左右,如果你的图片很大,序列化后的JSON Data可能会占用较多内存。如果遇到内存警告,可以考虑优化图片尺寸后再编码,或者和后端沟通是否支持分块上传(虽然你说不支持multipart,但分块上传可能是另一种方案)。
- Content-Type头:一定要手动设置
application/json,否则Alamofire默认可能会把Data的Content-Type设为application/octet-stream,导致服务器无法正确解析JSON。
内容的提问来源于stack exchange,提问作者swalkner
相关产品推荐
相关产品推荐

