Alamofire - 使用照片时图像上传失败

Posted

技术标签:

【中文标题】Alamofire - 使用照片时图像上传失败【英文标题】:Alamofire - Image Upload fails when using photos 【发布时间】:2017-06-23 12:41:26 【问题描述】:

尊敬的 *** 社区,

我正在使用 Alamofire 将 JSON 和图像发送到 REST API 的 ios 应用程序中工作。使用图像选择器检索图像并存储在数组中。问题是,只要我使用从互联网等下载的图像,图像上传就可以工作。一旦我尝试上传一张照片,这张照片是用我当前使用的手机拍摄的(从照片库中选择),上传失败并抛出 400 - Bad Request 错误。奇怪的是,当我可以上传照片时,这些照片是从另一部 iPhone 拍摄的,但已发送给我,但是用手机本身拍摄的照片却无法正常工作......有人知道为什么会出现这个问题发生?我怀疑 iPhone 照片的格式或数据可能与下载的照片不同,因为 HDR 和其他东西,但我不确定这是否是问题所在。

这是我使用的代码,但它非常标准:

func POST_WITH_ATACHMENTS(description: String, attachments: [UIImage], returnCompletion: @escaping (Bool) -> ()) 
    let parameters = ["ticket":" \"description\" : \"" + description + "\""]

    APIManager.Manager.upload(multipartFormData:  multipartFormData in
        for (key, value) in parameters 
            multipartFormData.append((value.data(using: .utf8)!), withName: key, mimeType: "application/json")
        

        var counter = 1
        for image in attachments 
            multipartFormData.append(UIImagePNGRepresentation(image)!, withName: "attachments", fileName: "attachment" + String(counter) + ".png", mimeType: "image/png")
            counter += 1
        
    ,
                     to: restURL!,
                     method: .post,
                     headers:["Authorization" : loginString],
                     encodingCompletion:  encodingResult in
                        switch encodingResult 
                        case .success(let upload, _, _):
                            upload.responseJSON  response in
                                debugPrint(response)
                                if (upload.response?.statusCode == 201) 
                                    returnCompletion(true)
                                 else 
                                    returnCompletion(false)
                                
                            
                        case .failure(let encodingError):
                            print(encodingError)
                            returnCompletion(false)
                        
    )

【问题讨论】:

尝试使用 image/jpeg 作为 mime 类型。因为这对于大多数图像格式都很常见,例如.jpg.jpeg.jfif 我尝试了您的解决方案并发现,这取决于我认为的图像大小...如果我将调整大小因子设置为 0.5,则照片上传有效,但未压缩它会失败... . 奇怪,服务器可能不支持那么大的图像。谢谢! Alamofire 中有一个选项可用于流式传输您的内容。看看它。可能对上传大尺寸图片有用。 @RobertBarta 使用我的方法使用 AlamoFire 上传图片 【参考方案1】:

这是使用 AlamoFire 上传图片的网络服务

class WebServiceHandler: AnyObject 

    func uploadWithAlamofire(Parameters params : [NSObject : AnyObject]?,ImageParameters imgparams :  [NSObject : AnyObject]?,Action action : NSString, success: @escaping (AnyObject) -> Void, failure: @escaping (AnyObject) -> Void)
    
        var base_url = "YOUR BASE_URL"
        base_url.append(action as String)

        Alamofire.upload(multipartFormData:  multipartFormData in
            if imgparams != nil
                for (key, value) in imgparams! 
                    if let imageData = UIImageJPEGRepresentation(value as! UIImage, 1) 
                        multipartFormData.append(imageData, withName: key as! String, fileName: "\(NSDate().timeIntervalSince1970 * 1000)).jpg", mimeType: "image/jpg")
                    
                
            

            if params != nil
            
                for (key, value) in params! 
                    multipartFormData.append((value as! String).data(using: .utf8)!, withName: key as! String)
                

             , to: base_url, method: .post, headers: nil,
                 encodingCompletion:  encodingResult in
                    switch encodingResult 
                    case .success(let upload, _, _):
                        upload.uploadProgress  progress in
                            print(progress.fractionCompleted)
                        
                        upload.response  [weak self] response in
                            guard self != nil else 
                                return
                            
                            let responseString = String(data: response.data!, encoding: String.Encoding.utf8)
                            return success(responseString as AnyObject)

                        
                    case .failure(let encodingError):
                        print("error:\(encodingError)")
                        return failure(encodingError as AnyObject)
                    
        )
    
    func convertToDictionary(text: String) -> [String: Any]? 
        if let data = text.data(using: .utf8) 
            do 
                return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
             catch 
                print(error.localizedDescription)
            
        
        return nil
    



----------------------------USAGE-----------------------------

let dict_params = NSMutableDictionary()
dict_params.set("123", forKey:"YourKey")
dict_params.set("123", forKey:"YourKey")
.
.
.and so on

let imgparam = NSMutableDictionary()
imgparam.set(YourImagetoUpload, forKey: "YourKey")
//here YourImagetoUpload is like imageview.image or UIImage(named: "123.png")
imgparam.set(YourImagetoUpload, forKey: "YourKey")
.
.
.and so on


self.webservice.uploadWithAlamofire(Parameters: dict_params as [NSObject : AnyObject], ImageParameters: imgparam as [NSObject : AnyObject], Action: "API_ACTION_CALL", success:  (success) in
        print(success)
)  (error) in
        print(error)

【讨论】:

谢谢!该方法与我的相似,所以我认为问题确实出在服务器端,REST API 不支持那么大的图像,我可能会尝试建议的流版本,或者缩小图像,因为它们不需要完全解决我的项目。

以上是关于Alamofire - 使用照片时图像上传失败的主要内容,如果未能解决你的问题,请参考以下文章

使用 Alamofire 上传图像不成功

Swift - Alamofire - 从照片库上传文件

使用 multipartFormData 上传图像时 Alamofire 请求正文为零

Alamofire 上传失败,文件超过 1MB

使用方案 Alamofire watchOS 构建工作区 Alamofire 失败

使用 Alamofire 从 UIImagePickerController 上传图像