The question is pretty straightforward:
I need to upload a .zip file to a server, how do I do this within Swift using Siesta Framework?
Thank you.
The question is pretty straightforward:
I need to upload a .zip file to a server, how do I do this within Swift using Siesta Framework?
Thank you.
On
Actually the above answer is not completely true. Since Siesta supports POST request since long time you can do file upload (Content-Type: multipart/form-data) in YourAPI class following way (example for PNG or JPEG file upload):
class YourAPI {
static let sharedInstance = YourAPI()
private let service = Service(baseURL: "http://your_server/rest/service", standardTransformers: [.text, .image])
private init() {
// your init code
}
public enum ImageType {
case png
case jpeg
}
func generateBoundaryString() -> String {
return "Boundary-\(UUID().uuidString)"
}
func constructHttpBodyForImageUpload(withBoundary boundary: String, imageData: Data, fileName: String, imageType: ImageType) -> Data {
let body = NSMutableData()
var mimetype = "image/png" // default
if imageType == .jpeg {
mimetype = "image/jpeg"
}
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition:form-data; name=\"file\"; filename=\"\(fileName)\"\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append(imageData)
body.append("\r\n".data(using: String.Encoding.utf8)!)
body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
return body as Data
}
@discardableResult func uploadImage(_ imageData: Data, fileName: String, imageType: ImageType, onSuccess: @escaping () -> Void, onFailure: @escaping (String) -> Void) -> Request {
let boundary = generateBoundaryString()
let request = service.resource("/files/upload").request(.post) {
// See comments in Siesta Resource.swift class for .post
$0.httpBody = self.constructHttpBodyForImageUpload(withBoundary: boundary, imageData: imageData, fileName: fileName, imageType: imageType)
$0.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
}
// My Server returns me JSON back
request.onSuccess { entity in
guard let json: [String: String] = entity.typedContent() else {
onFailure("JSON parsing error")
return
}
guard let status = json["status"] else {
onFailure("Responce status is missing")
return
}
print("status = \(status)")
}.onFailure { (error) in
onFailure(error.userMessage)
}
return request
}
} // YourAPI
To use it (from your ViewController):
@IBAction func uploadImage(_ sender: AnyObject) {
guard let image = self.imageView.image else {
return
}
guard let imageData = UIImagePNGRepresentation(image) else {
return
}
var fileName = self.fileName.text!
if fileName.isEmpty {
fileName = UUID().uuidString + ".png"
}
print("fileName = \(fileName)")
YourAPI.sharedInstance.uploadImage(imageData, fileName: fileName, imageType: .png, onSuccess: {
print("success")
}, onFailure: { error in
print(error)
})
}
Additionally since few days there is a pull request on Siesta project guthub to implement: Convenience method for multipart/form-data requests, which can be soon a standard part of framework and can reduce the size of above boilerplate code.
According to the GitHub page of Siesta, it does not support file upload/download tasks at the moment. See this comparison chart: