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