iOS swift post请求二进制正文

我想从iOS(swift3)发出一个POST请求,它传递一大块原始字节作为正文。 我做了一些实验,这让我觉得以下工作:

let url = URL(string: "https://bla/foo/bar")! var request = URLRequest(url: url) request.httpMethod = "POST" request.httpBody = Data(hex: "600DF00D") let session = URLSession.shared let task = session.dataTask(with: request) { (data, response, error) in "DATA \(data ?? Data()) RESPONSE \(response) ERROR \(error)".print() } task.resume() 

在我尝试发送像单个0xF0这样简单的东西之前,我不知道这是一个问题。 在那时我的龙卷风服务器开始抱怨我发送它

 WARNING:tornado.general:Invalid x-www-form-urlencoded body: 'utf-8' codec can't decode byte 0xf0 in position 2: invalid continuation byte 

我只是想以某种方式设置一些标题? 或者我需要做些什么?

两种常见的解决方案是:

  1. 您的错误消息告诉我们Web服务期望x-www-form-urlencoded请求(例如key=value ),并且对于该value ,您可以执行二进制有效负载的base-64编码。

    遗憾的是,base-64字符串仍然需要进行百分比转义(因为Web服务器通常将+字符解析为空格),因此您必须执行以下操作:

     let base64Encoded = data .base64EncodedString(options: []) .addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)! .data(using: String.Encoding.utf8)! var body = "key=".data(using: .utf8)! body.append(base64Encoded) var request = URLRequest(url: url) request.httpBody = body request.httpMethod = "POST" request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") let task = URLSession.shared.dataTask(with: request) { data, response, error in guard error == nil else { print(error!) return } ... } task.resume() 

    哪里:

     extension CharacterSet { static let urlQueryValueAllowed: CharacterSet = { let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4 let subDelimitersToEncode = "!$&'()*+,;=" var allowed = CharacterSet.urlQueryAllowed allowed.remove(charactersIn: generalDelimitersToEncode + subDelimitersToEncode) return allowed }() } 

    有关该字符集的更多讨论,请参阅本答案中的第2点: https : //stackoverflow.com/a/35912606/1271826 。

    无论如何,当您在服务器上收到此信息时,您可以将其检索为然后反转base-64编码,并且您将获得原始二进制有效负载。

  2. 或者,您可以使用multipart/formdata请求(您可以在其中提供二进制有效负载,但您必须将其作为更广泛的multipart/formdata格式的一部分包装)。 如果您想自己这样做,请参阅https://stackoverflow.com/a/26163136/1271826 。

对于这两种方法,像Alamofire这样的库使得它更容易,让你摆脱构建这些请求的杂草。