I imagine that you’ve got already heard concerning the well-known multipart-data add approach that everybody likes to add information and submit kind knowledge, but when not, hopefully this text will enable you a bit bit to know these items higher.
Let’s begin with some idea. Don’t be concerned, it is only one hyperlink, concerning the multipart/form-data content material sort specification. To rapidly summarize it first I would wish to inform you a couple of phrases about how the HTTP layer works. In a nutshell, you ship some knowledge with some headers (give it some thought as a key-value person data object) to a given URL utilizing a way and as a response you may get again a standing code, some headers and possibly some kind of response knowledge too. 🥜
- HTTP request = Technique + URL + Headers + Physique (request knowledge)
- HTTP response = Standing code + Headers + Physique (response knowledge)
The request methodology & URL is fairly simple, the fascinating half is while you specify the Content material-Sort
HTTP header, in our case the multipart/form-data;boundary="xxx"
worth means, that we’ll ship a request physique utilizing a number of elements and we’ll use the “xxx” boundary string as a separator between the elements. Oh, by the way in which every half can have it is personal sort and identify, we’ll use the Content material-Disposition: form-data; identify="field1"
line to let the server find out about these fields, earlier than we truly ship the precise content material worth.
That is greater than sufficient idea for now, let me snow you the way we are able to implement all of this utilizing Swift 5. To start with, we want to have the ability to append string values to a Information object, so we’ll prolong Information sort with an ‘append string utilizing encoding’ methodology:
import Basis
public extension Information {
mutating func append(
_ string: String,
encoding: String.Encoding = .utf8
) {
guard let knowledge = string.knowledge(utilizing: encoding) else {
return
}
append(knowledge)
}
}
Subsequent, we want one thing that may assemble the HTTP multipart physique knowledge, for this objective we’ll construct a MultipartRequest
object. We are able to set the boundary once we init this object and we’ll append the elements wanted to assemble the HTTP physique knowledge.
The non-public strategies will assist to assemble every little thing, we merely append string values to the non-public knowledge object that holds our knowledge construction. The general public API solely consists of two add capabilities that you need to use to append a key-value primarily based kind area or a whole file utilizing its knowledge. 👍
public struct MultipartRequest {
public let boundary: String
non-public let separator: String = "rn"
non-public var knowledge: Information
public init(boundary: String = UUID().uuidString) {
self.boundary = boundary
self.knowledge = .init()
}
non-public mutating func appendBoundarySeparator() {
knowledge.append("--(boundary)(separator)")
}
non-public mutating func appendSeparator() {
knowledge.append(separator)
}
non-public func disposition(_ key: String) -> String {
"Content material-Disposition: form-data; identify="(key)""
}
public mutating func add(
key: String,
worth: String
) {
appendBoundarySeparator()
knowledge.append(disposition(key) + separator)
appendSeparator()
knowledge.append(worth + separator)
}
public mutating func add(
key: String,
fileName: String,
fileMimeType: String,
fileData: Information
) {
appendBoundarySeparator()
knowledge.append(disposition(key) + "; filename="(fileName)"" + separator)
knowledge.append("Content material-Sort: (fileMimeType)" + separator + separator)
knowledge.append(fileData)
appendSeparator()
}
public var httpContentTypeHeadeValue: String {
"multipart/form-data; boundary=(boundary)"
}
public var httpBody: Information {
var bodyData = knowledge
bodyData.append("--(boundary)--")
return bodyData
}
}
The final remaining two public variables are helpers to simply get again the HTTP associated content material sort header worth utilizing the correct boundary and the whole knowledge object that it’s best to to ship to the server. This is how one can assemble the HTTP URLRequest utilizing the multipart struct.
var multipart = MultipartRequest()
for area in [
"firstName": "John",
"lastName": "Doe"
] {
multipart.add(key: area.key, worth: area.worth)
}
multipart.add(
key: "file",
fileName: "pic.jpg",
fileMimeType: "picture/png",
fileData: "fake-image-data".knowledge(utilizing: .utf8)!
)
let url = URL(string: "https://httpbin.org/submit")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue(multipart.httpContentTypeHeadeValue, forHTTPHeaderField: "Content material-Sort")
request.httpBody = multipart.httpBody
let (knowledge, response) = strive await URLSession.shared.knowledge(for: request)
print((response as! HTTPURLResponse).statusCode)
print(String(knowledge: knowledge, encoding: .utf8)!)
As you possibly can see it is comparatively simple, you simply add the shape fields and the information that you just need to add, and get again the HTTP associated values utilizing the helper API. I hope this text will enable you to simulate kind submissions utilizing multipart requests with out problem. 😊