Swift UrlSession上传多图至Node.js后端仅收单图问题排查
问题:Swift上传多图到Node.js后端仅收到1张图片
我用Node.js后端,通过multer的fields方法配置接收名为externalImages的图片数组(最多10张),Postman测试正常返回上传的图片详情。但用Swift的URLSession构造multipart/form-data请求上传多图时,后端只能收到1张图片,不想用第三方库,附两端代码求问题原因及解决方法。
后端代码
router.post('/imagesTest',multer().fields([{ name: 'externalImages', maxCount: 10 }]),adminController.imagesTest) exports.imagesTest = async (req, res) => { console.log(req.files['externalImages']) res.send(req.files['externalImages']) };
原Swift代码
func imagesTest(imageDataArray : [Data]) -> AnyPublisher<APIResponse, Error> { print("================= TEST IMAGES ") let boundary = UUID().uuidString var request = URLRequest(url: URL(string: "\(Constants.baseUrl)/admin/imagesTest")!) request.httpMethod = "POST" request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") request.httpBody = createMultiImageMultiPartBody(boundary: boundary, imageDataArray: imageDataArray) return URLSession.shared.dataTaskPublisher(for: request) .receive(on: RunLoop.main) .map({$0.data}) .decode(type: APIResponse.self, decoder: JSONDecoder()) .eraseToAnyPublisher() } func createMultiImageMultiPartBody(boundary : String,imageDataArray : [Data]) -> Data { var body = Data() let mimetype = "image/jpg" for imageData in imageDataArray{ body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!) body.append("Content-Disposition: form-data; name=\"externalImages\"; filename=\"\(Date().timeIntervalSince1970).jpg\"\r\n".data(using: String.Encoding.utf8)!) body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!) body.append(imageData) body.append("\r\n".data(using: String.Encoding.utf8)!) body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!) } return body }
问题原因
问题出在Swift的createMultiImageMultiPartBody方法中:你在每遍历一张图片后就添加了请求结束边界--\(boundary)--\r\n,这会让multipart请求在第一张图片后就被标记为完整结束,后端解析时会忽略后续所有图片数据,因此只能收到第一张图片。
解决方法
将结束边界的代码移出循环,仅在所有图片都添加完成后再添加一次结束边界。循环内只需要添加分隔边界(--\(boundary)\r\n)来区分不同的图片字段。
修正后的Swift代码
func imagesTest(imageDataArray : [Data]) -> AnyPublisher<APIResponse, Error> { print("================= TEST IMAGES ") let boundary = UUID().uuidString var request = URLRequest(url: URL(string: "\(Constants.baseUrl)/admin/imagesTest")!) request.httpMethod = "POST" request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") request.httpBody = createMultiImageMultiPartBody(boundary: boundary, imageDataArray: imageDataArray) return URLSession.shared.dataTaskPublisher(for: request) .receive(on: RunLoop.main) .map({$0.data}) .decode(type: APIResponse.self, decoder: JSONDecoder()) .eraseToAnyPublisher() } func createMultiImageMultiPartBody(boundary : String,imageDataArray : [Data]) -> Data { var body = Data() let mimetype = "image/jpg" for imageData in imageDataArray{ body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!) body.append("Content-Disposition: form-data; name=\"externalImages\"; filename=\"\(Date().timeIntervalSince1970).jpg\"\r\n".data(using: String.Encoding.utf8)!) body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!) body.append(imageData) body.append("\r\n".data(using: String.Encoding.utf8)!) // 移除循环内的结束边界 } // 所有图片添加完成后,添加一次结束边界 body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!) return body }
内容的提问来源于stack exchange,提问作者Mohammed Riyadh
相关产品推荐
相关产品推荐

