使用 swift POST 二进制数据
Posted
技术标签:
【中文标题】使用 swift POST 二进制数据【英文标题】:POST binary data using swift 【发布时间】:2018-08-21 06:19:02 【问题描述】:我想通过 RxAlamofire、Alamofire 甚至没有任何库发布二进制数据,但经过几天的研究和尝试,我无法做到。
在这里您可以找到我试图重现的请求的 POSTMAN 示例:
是一个 post 方法,带有 Authorization 和 Content-Type 标头以及附加的二进制数据。
我试图找到一些示例或相关内容,但找不到解决方案。我只能找到多部分表单数据示例,但是对于多部分表单数据,服务器无法正常工作(是外部 API)
如果有人可以指导我或给我看一些示例代码。
这里以用于登录的代码为例,向您展示我想要实现的目标:
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)
这里是 LoginResponse 对象:
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"]
最后是 APIRouter 扩展 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
提前谢谢你!
EDIT 转换成 RxAlamofire
使用下面的代码,我可以解决问题并将其转换为 RxSwift,但我想使用 RxAlamofire 来获得相同的结果:
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();
)
【问题讨论】:
您是否尝试过使用 Postman 生成的示例代码? (右上角Save
下的Code
按钮可让您生成有效的Swift 或Objective-C 代码)
@d.felber 是的,我试过但还是不行,POSTMAN 代码不包括二进制数据。
【参考方案1】:
Alamofire.upload()
(返回 UploadRequest
)可能会做你想做的事:
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
这个例子不包括 RxAlamofire - 但我很确定它有一个类似的upload
函数。希望对你有帮助!
【讨论】:
嗨,谢谢,它正在工作。我正在做类似的事情,但我不知道为什么我无法得到响应。 @BrunoRxAlamofire
似乎也有一个upload
函数:github.com/RxSwiftCommunity/RxAlamofire/blob/master/Sources/…
是的,问题是我找不到将 UploadRequest 响应转换为带有 Observable 的 DataResponse 的方法。使用 UploadRequest Observable 我可以获得 DataResponse 但在 completionHandler 中。以上是关于使用 swift POST 二进制数据的主要内容,如果未能解决你的问题,请参考以下文章
JMeter没有将二进制文件的内容附加到HTTP请求中的POST数据
如何通过 C 中的 HTTP POST 请求发送图像或二进制数据