如何使用Moya Swift进行多部分请求上传图片?

18

我正在使用 Moya 10.0.1,当尝试将图片上传到服务器时遇到了问题。

我已经按照Multipart上传示例操作,并且这是我的设置代码:

typealias UpdateUserAvatarParameters = (userId: Int, image: UIImage)

enum APITarget {
    case updateUserAvatar(parameters: UpdateUserAvatarParameters)
}

extension APITarget: TargetType {

    public var baseURL: URL { return URL(string: "http://domain/api")! }

    public var path: String {
        switch self {
        case .updateUserAvatar: return "/postuserimage"
        }
    }

    public var method: Moya.Method {
        switch self {
        default: return .post
        }
    }

    public var task: Task {
        switch self {
        case .updateUserAvatar(let parameters):
            let imageData = UIImagePNGRepresentation(parameters.image) ?? Data()
            let userIdData = parameters.userId.string.data(using: String.Encoding.utf8) ?? Data()

            let imageMultipartFormData = MultipartFormData(provider: .data(imageData), name: "img", fileName: "user_avatar.jpeg", mimeType: "image/jpeg")
            let userIdMultipartFormData = MultipartFormData(provider: .data(userIdData), name: "cusId")

            return .uploadMultipart([imageMultipartFormData, userIdMultipartFormData])
        }
    }

    public var sampleData: Data {
        return Data()
    }

    public var headers: [String : String]? {
        switch self {
        case .updateUserAvatar: return ["Content-type" : "multipart/form-data"]
        default: return ["Content-type" : "application/json"]
        }
    }
}

然而,当我发出请求时,我收到了一个 MoyaError:

let parameters = UpdateUserAvatarParameters(userId: 1, image: pickedImage)

provider.request(.updateUserAvatar(parameters: parameters), completion: { result in
    switch result {
    case .success(let response):
        do {
            try _ = response.filterSuccessfulStatusCodes()
            print("200 - 299: \(response.data)")
        } catch {
            print(error)  // This code will run because the statusCode is 500
        }

    case .failure(let error):
        print("Failure: \(error)")
    }
})

在此输入图片描述

我不知道我的错误在哪里,也不知道statusCode 500是什么意思?有人知道为什么吗?

另外,当我使用相同的设置(URL、参数等)使用Alamofire进行请求时,一切正常:

Alamofire.upload(multipartFormData: { multipartFormData in
    let imageData = UIImagePNGRepresentation(pickedImage) ?? Data()
    let userIdData = userId.string.data(using: String.Encoding.utf8) ?? Data()

    multipartFormData.append(imageData, withName: "img", fileName: "user_avatar.jpeg", mimeType: "image/jpeg")
    multipartFormData.append(userIdData, withName: "cusId")
}, to: "http://domain/api/postuserimage", encodingCompletion: { result in
    switch result {
    case .success(let upload, _, _):
        upload.uploadProgress(closure: { progress in
            print("Upload Progress: \(progress.fractionCompleted)")
        })

        upload.responseJSON(completionHandler: { response in
            print(response.result.value)
        })

    case .failure(let encodingError):
        print(encodingError)
    }
})
2个回答

21
    var task: Task {
    switch self {
    case .updateProfilePic(let memberID, let image):
        let imageData = UIImageJPEGRepresentation(image, 1.0)
        let memberIdData = memberID.data(using: String.Encoding.utf8) ?? Data()
        var formData: [Moya.MultipartFormData] = [Moya.MultipartFormData(provider: .data(imageData!), name: "user_img", fileName: "user.jpeg", mimeType: "image/jpeg")]
        formData.append(Moya.MultipartFormData(provider: .data(memberIdData), name: "member_id"))
        return .uploadMultipart(formData)
    }

在Moya的多部分请求中,我们需要将参数作为multipartdata表单传递,并附带它的键名。


self.parameters!是什么?你在哪里声明它? - Anh Pham
根据Moya的文档uploadCompositeMultipart(_:urlParameters)用于URL参数的情况(例如GET)。在我的情况下,HTTP方法是POST,这意味着参数是请求体的一部分,因此我使用.uploadMultipart(_:) - Anh Pham
@AnhPham self.parameters 是为枚举服务创建的自定义计算属性。 - Pratik Sodha
@PratikSodha:您能否指定如果有多个图像要在单个键用户_img下发送,我们该如何做到这一点? - Gaurav
如果有人在寻找相关信息,回复我的评论可能会有所帮助。如果你正在使用MOYA库,这个链接可能会对你有用。 https://github.com/Moya/Moya/issues/598#issuecomment-247144457 - Gaurav
我可以在使用MultipartFormData时使用pngData吗?我希望上传后保持图像格式。 - Quyen Anh Nguyen

2

使用Moya Swift进行多部分请求上传图像的完整详细信息。 步骤1

 import Foundation
import Moya

enum ImageService {
    case updateUserAvatar(user_id: Int, cover_image: UIImage)
}
extension ImageService: TargetType {
    public var baseURL: URL { return URL(string: "https://api.shoclef.com/api")! }
    public var path: String {
        switch self {
        case .updateUserAvatar(_,_): return "/updatecoverimage"
        }
    }
    public var method: Moya.Method {
        switch self {
        case .updateUserAvatar(_, _):
            return .post
        }
    }
    var task: Task {
        switch self {

    case .updateUserAvatar(let user_id, let cover_image):
        let imageData = UIImageJPEGRepresentation(cover_image, 1.0)
        let memberIdData = "\(user_id)".data(using: String.Encoding.utf8) ?? Data()
        var formData: [Moya.MultipartFormData] = [Moya.MultipartFormData(provider: .data(imageData!), name: "cover_image", fileName: "asdas.png", mimeType: "image/jpeg")]
        formData.append(Moya.MultipartFormData(provider: .data(memberIdData), name: "user_id"))
        return .uploadMultipart(formData)
    }
}
public var sampleData: Data {
    return Data()
}
public var headers: [String : String]? {
    switch self {
    case .updateUserAvatar: return ["Content-type" : "application/json"]

    }}}

第二步

@IBOutlet weak var myImage: UIImageView!
    var provider = MoyaProvider<ImageService>()
 @IBAction func uploadImage(_ sender: UIButton) {
        provider.request(ImageService.updateUserAvatar(user_id: 1163, cover_image: myImage.image!)) { result in
            switch result {
            case .success(let response):
                do {

                    let image = try JSONDecoder().decode(Updatecoverimage.self, from: response.data)
                    print(image.data)
                } catch {
                    print(error)  // This code will run because the statusCode is 500
                }

            case .failure(let error):
                print("Failure: \(error)")
            }
        }

    }

}



struct Updatecoverimage: Codable {
    let status, data: String
}

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