HomeiOS DevelopmentSimple multipart file add for Swift

Simple multipart file add for Swift



I imagine that you’ve got already heard in regards to the well-known multipart-data add method that everybody likes to add information and submit kind information, but when not, hopefully this text will assist you to a bit bit to know these items higher.


Let’s begin with some idea. Don’t be concerned, it is only one hyperlink, in regards to the multipart/form-data content material kind specification. To shortly summarize it first I might prefer to inform you a couple 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 data object) to a given URL utilizing a technique and as a response you will get again a standing code, some headers and perhaps some kind of response information too. 🥜


  • HTTP request = Technique + URL + Headers + Physique (request information)
  • HTTP response = Standing code + Headers + Physique (response information)


The request methodology & URL is fairly simple, the attention-grabbing half is if 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 way in which every half can have it is personal kind 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 really 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 Knowledge object, so we will lengthen Knowledge kind 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’d like 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 non-public strategies will assist to assemble every thing, we merely append string values to the non-public information object that holds our information construction. The general public API solely consists of two add features that you should use to append a key-value primarily based kind discipline or a complete file utilizing its information. 👍


public struct MultipartRequest {
    
    public let boundary: String
    
    non-public let separator: String = "rn"
    non-public var information: Knowledge

    public init(boundary: String = UUID().uuidString) {
        self.boundary = boundary
        self.information = .init()
    }
    
    non-public mutating func appendBoundarySeparator() {
        information.append("--(boundary)(separator)")
    }
    
    non-public mutating func appendSeparator() {
        information.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()
        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 kind header worth utilizing the correct 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/publish")!
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 may see it is comparatively simple, you simply add the shape fields and the information that you simply need to add, and get again the HTTP associated values utilizing the helper API. I hope this text will assist you to to simulate kind submissions utilizing multipart requests with out problem. 😊


RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments