1

I would like to post binary data through RxAlamofire, Alamofire or even without any library but after some days of research and tries, I'm not able to do it.

Here you can find the POSTMAN example of the request that I am trying to reproduce is:

captura de pantalla 2018-08-20 a las 13 42 36 captura de pantalla 2018-08-20 a las 13 42 48

Is a post method with the Authorization and Content-Type headers and the binary data attached.

I have tried to find some example or something related but I couldn't find a solution. I could just find multipart form data examples but with multipart form data the server doesn't work (is a external API)

If someone could guide me or show me some example code.

Here the code used for login as example and to show you something that I want to achieve:

public class APIClient: DataSource {

    public static var shared: APIClient = APIClient()

    private init(){}

    public func login(email:String, password:String) -> Observable<LoginResponse> {
        return RxAlamofire.requestJSON(APIRouter.login(email:email, password:password))
            .subscribeOn(MainScheduler.asyncInstance)
            .debug()
            .mapObject(type: LoginResponse.self)
    }

}

Here the LoginResponse object:

public struct LoginResponse: Mappable {
    var tokenId: String?
    var userId: String?

    public init?(map: Map) {}

    public mutating func mapping(map: Map) {
        tokenId <- map["id"]
        userId <- map["userId"]
    }

}

And finally the APIRouter extending URLRequestConvertible:

enum APIRouter: URLRequestConvertible {

    case login(email: String, password: String)

    private var method: HTTPMethod {
        switch self {
        case .login:
            return .post
        }
    }

    private var path: String {
        switch self {
        case .login:
            return "users/login"
        }
    }

    private var parameters: Parameters? {
        switch self {
        case .login(let email, let password):
            return [APIConstants.LoginParameterKey.email: email, APIConstants.LoginParameterKey.password: password]
        }
    }

    private var query: [URLQueryItem]? {
        var queryItems = [URLQueryItem]()
        switch self {
        case .login:
            return nil
        }
    }

    func asURLRequest() throws -> URLRequest {
        var urlComponents = URLComponents(string: APIConstants.ProductionServer.baseURL)!
        if let query = query {
            urlComponents.queryItems = query
        }

        var urlRequest = URLRequest(url: urlComponents.url!.appendingPathComponent(path))

        // HTTP Method
        urlRequest.httpMethod = method.rawValue

        urlRequest.addValue(ContentType.json.rawValue, forHTTPHeaderField: HTTPHeaderField.acceptType.rawValue)
        urlRequest.addValue(ContentType.json.rawValue, forHTTPHeaderField: HTTPHeaderField.contentType.rawValue)

            if let parameters = parameters {
                do {
                    urlRequest.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
                } catch {
                    throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
                }
            }


        return urlRequest
    }
}

Thank you in advance!

EDIT To convert into RxAlamofire

With the code below I could solve the problem and convert it into RxSwift but I would like to use RxAlamofire to obtain the same result:

public func upload(media: Data) -> Observable<ContentUri> {
        let headers = [
            "content-type": "image/png",
            "authorization": "token header"
        ]
        return Observable<ContentUri>.create({observer in
            Alamofire.upload(media, to: "\(endPoint)/api/media/upload", headers: headers)
                .validate()
                .responseJSON { response in
                    print(response)
            }
            return Disposables.create();
        })
    }
2
  • Did you try using the generated example code from Postman? (The Code button under Save on the top right lets you generate working Swift or Objective-C code) Commented Aug 21, 2018 at 6:25
  • @d.felber yes I tried but still not working, the POSTMAN code is not including the binary data. Commented Aug 21, 2018 at 6:31

1 Answer 1

3

Alamofire.upload() (which returns an UploadRequest) might do what you want:

let headers = [
    "Content-Type":"image/jpeg",
    "Authorization":"sometoken",
]

let yourData = ... // Data of your image you want to upload
let endPoint = ...

Alamofire.upload(yourData, to: "\(endPoint)/api/media/upload", headers: headers)
    .validate(statusCode: 200..<300)
    .responseJSON { response in
        // handle response
    }

This example does not include RxAlamofire - but I am pretty sure it has a similar upload function. I hope it helps!

Sign up to request clarification or add additional context in comments.

4 Comments

Hi thanks, it is working. I was doing something similar but I don't know why I couldn't get that response.
@Bruno RxAlamofire seems to also have an upload function: github.com/RxSwiftCommunity/RxAlamofire/blob/master/Sources/…
Yes, the problem is that I cannot find a way to convert the UploadRequest response into DataResponse with an Observable. With the UploadRequest Observable I can obtain the DataResponse but in a completionHandler.
how can we compose same request with nsurlsession?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.