Skip to content

Instantly share code, notes, and snippets.

@OscarSwanros
Created September 3, 2017 00:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OscarSwanros/1ae9fae243137e2de08318458962c3ec to your computer and use it in GitHub Desktop.
Save OscarSwanros/1ae9fae243137e2de08318458962c3ec to your computer and use it in GitHub Desktop.
File Upload to S3 in Swift
//
// UploadFileToS3Operation.swift
// VecinioAPIKit
//
// Created by Oscar Swanros on 9/2/17.
// Copyright © 2017 Vecinio Technologies Inc. All rights reserved.
//
final public class UploadFileToS3Operation: P3Operation {
public let image: UIImage
public var uploadDescriptor: S3UploadDescriptor?
public var uploadedFile: NetworkFile?
var session: URLSession?
private lazy var boundaryString: String = {
return "\(NSUUID().uuidString)"
}()
public init(image: UIImage, uploadDescriptor: S3UploadDescriptor? = nil) {
self.image = image
self.uploadDescriptor = uploadDescriptor
super.init()
addObserver(observer: P3NetworkActivityObserver())
}
public override func execute() {
guard let uploadDescriptor = uploadDescriptor else { fatalError("Can't start an upload without an upload descriptor") }
let url = URL(string: "https://bucket.s3.amazonaws.com/")
var request = URLRequest(url: url!, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData)
request.httpMethod = P3HTTPMethod.post.rawValue
request.setValue("multipart/form-data; boundary=\(boundaryString)", forHTTPHeaderField: "Content-Type")
request.httpBody = httpBody(with: uploadDescriptor.toDictionary, image: image)
session = URLSession(configuration: .default)
guard let s = session else {
finish();
return
}
let task = s.dataTask(with: request) { (data, response, error) in
defer { self.finish() }
let decoder = JSONDecoder()
guard let data = data else { return }
do {
let model = try decoder.decode(P3JSONResponseWrapper<NetworkFile>.self, from: data)
guard let inflated = model.data else { return }
self.uploadedFile = inflated
self.finished(model: inflated)
} catch {
print(error)
}
}
task.resume()
}
open func finished(model: NetworkFile) {
// For subclassing if needed
}
private func httpBody(with params: [String:String], image: UIImage) -> Data {
var body = Data()
guard let imageData = UIImageJPEGRepresentation(image, 0.5) else { return body }
for (key, value) in params {
body.append("--\(boundaryString)\r\n")
body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.append("\(value)\r\n")
}
body.append("--\(boundaryString)\r\n")
body.append("Content-Disposition: form-data; name=\"file\"\r\n\r\n")
body.append(imageData)
body.append("\r\n")
body.append("--\(boundaryString)--\r\n")
return body
}
}
extension Data {
mutating func append(_ string: String) {
if let data = string.data(using: .utf8) {
append(data)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment