使用Alamofire和multipart/form-data

4
我无法正确地访问提供给我的API以获取所需的响应。我已经使用Swift和Alamofire一段时间了,但这是我第一次使用multipart/form-data上传图像。我能够使用Postman上传图片,但我无法使用Alamofire框架发送相同的消息。

My Postman screenshot

我的 Swift 代码:

func postFulfilWish(wish_id: Int, picture : UIImage, completionHandler: ((AnyObject?, ErrorType?) -> Void)) {

    var urlPostFulfilWish = Constant.apiUrl;
    urlPostFulfilWish += "/wishes/";
    urlPostFulfilWish += String(wish_id);
    urlPostFulfilWish += "/fulfill/images"  ;

    let image : NSData = UIImagePNGRepresentation(UIImage(named: "location.png")!)!

    Alamofire.upload(.POST, urlPostFulfilWish, headers: Constant.headers, multipartFormData: { multipartFormData in
        multipartFormData.appendBodyPart(data: image, name: "file")
        },
        encodingCompletion: { encodingResult in
            switch encodingResult {
            case .Success(let upload, _, _):
                upload.responseJSON { response in
                    //This is where the code ends up now
                    //So it's able to encode my message into multipart/form-data but it's not doing it in the correct way for the API to handle it
                    debugPrint(response)
                }
            case .Failure(let encodingError):
                print(encodingError)
            }
        }
    )
}
4个回答

8

如果还没有得到答案,最近我也遇到了使用Alamofire上传form-data格式的图片的问题。

我通过Postman按照这篇文章展示的方法成功上传了图片,但在我的应用中却无法使用Alamofire实现。

你需要检查两个方面,首先是服务器期望接收的文件名称,其次是multipartFormData闭包中用于添加body部分的方法。

在我的情况下,这两种方法都不起作用-

multipartFormData.appendBodyPart(data: imageData, name: "file")

this one neither

multipartFormData.appendBodyPart(data: imageData, name: "file", fileName: name)

但是在这个项目中表现得不错 -
multipartFormData.appendBodyPart(data: imageData, name: "file", fileName: "file.jpeg", mimeType: "image/jpeg")

问题基本上是服务器找不到预期名称的文件。

我希望这能帮助某些人节省时间,不再纳闷为什么它不起作用。


你能看到我的问题吗,@EstebanVallejo [链接] (https://stackoverflow.com/questions/52887152/post-form-data-data-with-alamofire-not-work)? - Firuma
@Firuma,嘿,刚看到这个,我已经在你的帖子上回复了。 - Esteban Vallejo
fileName: "file.jpeg"1 这个参数对我很有帮助。在设置了除这个参数以外的所有内容后,一旦设置了这个参数,一切都正常工作了!谢谢! - Muhammad Yusuf

1
你正在执行debugPrint(response)。你可能需要另一个switch response.result { ... },查看请求的结果是否为.Success.Failure,如果是成功,则需要查看响应对象的内容(或者如果失败,则查看失败错误)。你需要查看result来诊断它是否成功。
Alamofire.upload(.POST, urlPostFulfilWish, headers: Constant.headers, multipartFormData: { multipartFormData in
    multipartFormData.appendBodyPart(data: image, name: "file")
}) { encodingResult in
    switch encodingResult {
    case .Success(let upload, _, _):
        upload.responseJSON { response in
            switch response.result {
            case .Success(let value):
                print(value)
            case .Failure(let error):
                print(error)
            }
        }
    case .Failure(let encodingError):
        print(encodingError)
    }
}

你的答案一开始没有编译通过,但是经过调试后我让它运行了。然而,它却进入了.Failure状态,并且给了我以下错误:2016-03-17 14:45:00.665 app[8675:806126] CUICatalog: Invalid asset name supplied: (Optional(<>), Error Domain=NSCocoaErrorDomain Code=3840 "No value." UserInfo={NSDebugDescription=No value.})我认为这可能与Alamofire没有发送与Postman相同的请求有关。如何使它发送与上面截图中完全相同的请求? - Rutger Huijsmans
@RutgerHuijsmans - 我倾向于使用Charles观察两个请求,比较并分析它们之间的差异。使用您分享给我们的屏幕快照很难理解原始请求的样子。另外,您确定要使用appendBodyPart(name:)而不是appendBodyPart(name:fileType:mimeType:)吗? - Rob

1
我最近在发送一个带有参数的multipart请求时从服务器收到了404错误。我使用了UIImagePickerController(其代理返回UIImage),然后发送了它的PNG表示。只有磁盘上为JPEG格式的文件才会出现这种情况。奇怪的是,这个问题似乎只影响了同时在body中有参数的multipart请求。当API端点不需要其他内容时,它可以正常工作。我猜测,在JPEG -> UIImage -> PNG表示的过程中发生了一些奇怪的事情,导致某种问题,这种问题奇怪地只在同时在body中有参数的multipart请求中显现出来。可能是一些特殊字符使服务器无法识别请求并返回404。我最终通过发送所选图像的UIImageJPEGRepresentation而不是UIImagePNGRepresentation来解决了这个问题,没有出现这样的错误。

0

我相信这个问题已经过时了,但只要没有被接受的答案,可以尝试以下方法:

multipartFormData.appendBodyPart(data: imageData, name: "name", fileName: "filename", mimeType: mimeType)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接