Swift base 64 string DIRECTLY to Jpeg on filesystem - ios

I am getting base64 images in an API call and I need to store these as files locally.
I was trying to write this data without having to convert the string to UIImage and then UIImage to JPEGRepresentation.
I don't want the overhead of creating UIImages first and theen changing to JPEGs if I can avoid it, but I don't know if this is possible?
I can see in my app Container, that all the files are there and the correct filesize but when I try to open them, they won't and I am told they may be corrupt.
extension NSData {
func writeToURL2(named:URL, completion: #escaping (_ result: Bool, _ url:NSURL?) -> Void) {
let tmpURL = named as NSURL
DispatchQueue.global(qos: .background).async { [weak self] () -> Void in
guard let strongSelf = self else { completion (false, tmpURL); return }
strongSelf.write(to: tmpURL as URL, atomically: true)
var error:NSError?
if tmpURL.checkResourceIsReachableAndReturnError(&error) {
print("We have it")
completion(true, tmpURL)
} else {
print("We Don't have it\(error?.localizedDescription)")
completion (false, tmpURL)
}
}
}
}
and it is used like:
for employee in syncReponse
{
autoreleasepool{
if let employeeJsonStr = employee["data"] as? String{
if let employeeDataDict = try? JSONSerializer.toDictionary(employeeJsonStr), let proPic = employeeDataDict["profilepicture"] as? String, proPic.removingWhitespaces() != "", let idStr = employeeDataDict["employeeId"] as? String, let proPicData = (proPic.data(using: .utf8)) {
let empPicDir = mainDir.appendingPathComponent(util_Constants.DIR_EMP_PICS)
let filename = empPicDir.appendingPathComponent(idStr+".jpg")
(proPicData as NSData).writeToURL2(named: filename, completion: { (result, url) -> Void in
})
}
let Emp = DATA_EP_employee(employeeJsonStr : employeeJsonStr)
dataList.append(Emp)
reqCount += 1
}
}
}

Related

delete file from s3 bucket swift

I have used this answer to delete a file from s3 bucket
The task I need to perform is when I'm uploading a new image I need to delete the previous one. So after upload, I'm calling deletion for the previous image. The deletion method gives me success but the file is still there in a bucket. So now, I can see both of the files; the previous one and the new one too. Am I missing something?
Here's my code of upload & delete
func uploadfile(image: UIImage, s3Key: String, bucketName: String, completionHandlerWithImageURL: #escaping(_ imageurl: String) -> ())
{
let transfer_utility = S3TransferUtilityConfig().config()
let expression = S3Expression().config()
var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
completionHandler = { (task, error) -> Void in
debugPrint("Upload Completed")
}
let bucketName = bucketName
guard let data = image.pngData() else{
return
}
transfer_utility?.uploadData(data as Data, bucket: bucketName, key: s3Key, contentType: "image/png", expression: expression,
completionHandler: completionHandler).continueWith
{
(task) -> AnyObject? in
if let error = task.error {
print(error.localizedDescription)
completionHandlerWithImageURL("")
}
if let _ = task.result {
debugPrint("Uploaded image successfully")
if task.result != nil {
let url = AWSS3.default().configuration.endpoint.url
let publicURL = url?.appendingPathComponent(bucketName).appendingPathComponent(s3Key)
if let absoluteString = publicURL?.absoluteString {
debugPrint("Image Url :\(absoluteString)")
completionHandlerWithImageURL(absoluteString)
}
} else {
debugPrint("Image URL not generated")
completionHandlerWithImageURL("")
}
}
return nil
}
}
func deleteExistingFile(s3Key: String, bucketName: String) {
let s3 = AWSS3.default()
guard let deleteObjectRequest = AWSS3DeleteObjectRequest() else { return }
deleteObjectRequest.bucket = bucketName
deleteObjectRequest.key = "/images/\(s3Key.components(separatedBy: "/").last ?? "")"
s3.deleteObject(deleteObjectRequest).continueWith { (task:AWSTask) -> AnyObject? in
if let error = task.error {
print("Error deleting file on s3 bucket: \(error)")
return nil
} else {
print("s3 file Deleted successfully. \(bucketName) \(s3Key)")
return nil
}
}
}
This is how I have called both the methods.
S3Manager.shared.uploadfile(image: image, s3Key: self.img_key, bucketName: (company_profile["dot"] as? String ?? ""))
{ (imgUrl) in
if imgUrl != ""
{
S3Manager.shared.deleteExistingFile(s3Key: self.profileUrl, bucketName: (company_profile["dot"] as? String ?? ""))
...
...
}
}
Uploaded image path:
https://s3.us-east-1.amazonaws.com/bucketNumber/images/img.png
I have tried deleteObjectRequest.key with the full path and only the folder / image path and in both the cases, method gives success but file is still there in a bucket.
deleteObjectRequest.key:
https://bucketName.s3.amazonaws.com/images/old_img.png
deleteObjectRequest.key:
/images/old_img.png

Handle completion with asynchronous call in for loop [duplicate]

This question already has answers here:
Completion gets called soon
(2 answers)
Closed 2 years ago.
I have a function that should have a completion-handler which should only be called if everything inside of it is actually completed. That is my function:
static func getWishes(dataSourceArray: [Wishlist], completion: #escaping (_ success: Bool, _ dataArray: [Wishlist]) -> Void){
var dataSourceArrayWithWishes = dataSourceArray
let db = Firestore.firestore()
let userID = Auth.auth().currentUser!.uid
for list in dataSourceArray {
db.collection("users").document(userID).collection("wishlists").document(list.name).collection("wünsche").order(by: "wishCounter").getDocuments() { ( querySnapshot, error) in
if let error = error {
print(error.localizedDescription)
completion(false, dataSourceArrayWithWishes)
} else {
// append every Wish to array at wishIDX
for document in querySnapshot!.documents {
let documentData = document.data()
let imageUrlString = document["imageUrl"] as? String ?? ""
let imageView = UIImageView()
imageView.image = UIImage()
if let imageUrl = URL(string: imageUrlString) {
let resource = ImageResource(downloadURL: imageUrl)
imageView.kf.setImage(with: resource) { (result) in
switch result {
case .success(_):
dataSourceArrayWithWishes[wishIDX].wishes.append(Wish(name: name, link: link, price: price, note: note, image: imageView.image!, checkedStatus: false))
completion(true, dataSourceArrayWithWishes)
print("success")
case .failure(_):
print("fail")
}
}
} else {
dataSourceArrayWithWishes[wishIDX].wishes.append(Wish(name: name, link: link, price: price, note: note, image: imageView.image!, checkedStatus: false))
}
}
}
}
}
}
The problem lies in imageView.kf.setImage...
Right now I am calling completion after the first .success but the function should only be completed if the for-loop and all the setImages are being finished. I've tried a couple of things now but I can not make it work. So I wonder what's best practice for this case?
Here is how you use DispatchGroup for this... You need DispatchGroup to get notified when the asynchronous loop is finished
static func getWishes(dataSourceArray: [Wishlist], completion: #escaping (_ success: Bool, _ dataArray: [Wishlist]) -> Void){
var dataSourceArrayWithWishes = dataSourceArray
let db = Firestore.firestore()
let userID = Auth.auth().currentUser!.uid
let group = DispatchGroup()
for list in dataSourceArray {
group.enter()
db.collection("users").document(userID).collection("wishlists").document(list.name).collection("wünsche").order(by: "wishCounter").getDocuments() { ( querySnapshot, error) in
defer{ group.leave() }
if let error = error {
print(error.localizedDescription)
completion(false, dataSourceArrayWithWishes)
} else {
// append every Wish to array at wishIDX
for document in querySnapshot!.documents {
group.enter()
let documentData = document.data()
let imageUrlString = document["imageUrl"] as? String ?? ""
let imageView = UIImageView()
imageView.image = UIImage()
if let imageUrl = URL(string: imageUrlString) {
let resource = ImageResource(downloadURL: imageUrl)
imageView.kf.setImage(with: resource) { (result) in
defer{ group.leave() }
switch result {
case .success(_):
dataSourceArrayWithWishes[wishIDX].wishes.append(Wish(name: name, link: link, price: price, note: note, image: imageView.image!, checkedStatus: false))
case .failure(_):
print("fail")
}
}
} else {
dataSourceArrayWithWishes[wishIDX].wishes.append(Wish(name: name, link: link, price: price, note: note, image: imageView.image!, checkedStatus: false))
}
}
}
}
}
group.notify(queue: DispatchQueue.main) {
completion(true, dataSourceArrayWithWishes)
print("success")
}
}

Issue with unwrapping [String] when using image cache

I'm trying to rewrite my image cache to get away from using Alamofire, and in doing so I've run into an error. Previously, my image cache code was:
let imageCache = NSCache<NSString, UIImage>()
extension UIImageView {
func loadImageUsingCacheWithUrlString(_ urlString: String) {
self.image = nil
// Check cache for image first
if let cachedImage = imageCache.object(forKey: urlString as NSString) {
self.image = cachedImage
return
}
// Otherwise fire off a new download
Alamofire.request(urlString)
.responseImage { response in
if let downloadedImage = response.result.value {
// image is here.
imageCache.setObject(downloadedImage, forKey: urlString as NSString)
self.image = downloadedImage
}
}
}
}
And an example use is as follows:
navBarCell.avatarImageView.loadImageUsingCacheWithUrlString(avatars[indexPath.row])
Now I've rewritten the cache like so:
class ImageService {
static let cache = NSCache<NSString, UIImage>()
static func downloadImage(url: URL, completion: #escaping (_ image: UIImage?) -> (Void)) {
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else {return}
var downloadedImage: UIImage?
downloadedImage = UIImage(data: data)
if downloadedImage != nil {
cache.setObject(downloadedImage!, forKey: url.absoluteString as NSString)
}
DispatchQueue.main.async {
completion(downloadedImage)
}
}.resume()
}
static func getImage(url: URL, completion: #escaping (_ image: UIImage?) -> (Void)) {
if let image = cache.object(forKey: url.absoluteString as NSString) {
completion(image)
} else {
downloadImage(url: url, completion: completion)
}
}
}
And to use it in the same scenario as above:
if let avatarImageUrlString = self.chatVC?.avatarDictionary.allValues as! [String], let imageUrl = URL(string: avatarImageUrlString) {
ImageService.getImage(url: imageUrl, completion: { (image) -> (Void) in
navBarCell.avatarImageView.image = image
})
}
And I'm getting the error Initializer for conditional binding must have Optional type, not '[String]' on the if let statement.
I'm not sure how to handle this - I need the [String] array but if I'm understanding the error correctly it needs to be an optional instead of force unwrapping with as! [String]? I apologize if its a newbie question but I can't seem to get it working.
Thanks for any guidance!
EDIT:
I've tried putting the let avatarImageUrlString.... outside of the if let:
let avatarImageUrlString = self.chatVC?.avatarDictionary.allValues as! [String]
if let imageUrl = URL(string: avatarImageUrlString) {
ImageService.getImage(url: imageUrl, completion: { (image) -> (Void) in
navBarCell.avatarImageView.image = image
})
}
But get the error Cannot convert value of type '[String]' to expected argument type 'String' on the if let line.
I've also tried removing the ! and I get the error '[Any]?' is not convertible to '[String]'; did you mean to use 'as!' to force downcast? with the fix recommendation of putting the ! back in: Replace 'as' with 'as!'
EDIT 2:
if let avatarImageUrlString = self.chatVC?.avatarDictionary.allValues as? [String], let imageUrl = URL(string: avatarImageUrlString[0]) {
ImageService.getImage(url: imageUrl, completion: { (image) -> (Void) in
navBarCell.avatarImageView.image = image
})
}
EDIT 3:
let avatars = self.chatVC?.avatarDictionary.allValues[indexPath.row] as? [String]
if let avatarImageUrlString = avatars, let imageUrl = URL(string: avatarImageUrlString[0]) {
ImageService.getImage(url: imageUrl, completion: { (image) -> (Void) in
navBarCell.avatarImageView.image = image
})
}
You're actually force-unwrapping allValues as [String] so then there is nothing to downcast. Also change type from array of strings to single string
So instead of this in optional-binding
as! [String]
use this
as? String
So...
if let avatarImageUrlString = self.chatVC?.avatarDictionary.allValues[indexPath.row] as? String, let imageUrl = URL(string: avatarImageUrlString) {
...
}

Decoding API data

I'm trying to fetch data from an API but I can't get it right and I don't know the issue here:
struct BTCData : Codable {
let close : Double
let high : Double
let low : Double
private enum CodingKeys : Int, CodingKey {
case close = 3
case high = 4
case low = 5
}
}
func fetchBitcoinData(completion: #escaping (BTCData?, Error?) -> Void) {
let url = URL(string: "https://api.bitfinex.com/v2/candles/trade:30m:tBTCUSD/hist")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else { return }
do {
if let bitcoin = try JSONDecoder().decode([BTCData].self, from: data).first {
print(bitcoin)
completion(bitcoin, nil)
}
} catch {
print(error)
}
}
task.resume()
}
I'd like to be able to access close in every dict and iterate like that:
var items : BTCData!
for idx in 0..<15 {
let diff = items[idx + 1].close - items[idx].close
upwardMovements.append(max(diff, 0))
downwardMovements.append(max(-diff, 0))
}
I get nil. I don't understand how to decode this kind of API where I need to iterate something which is not inside another dict.
EDIT: The above was solved and I'm now struggling to use [BTCData] in another function.
I am trying to use it here :
func fetchBitcoinData(completion: #escaping ([BTCData]?, Error?) -> Void) {
let url = URL(string: "https://api.bitfinex.com/v2/candles/trade:30m:tBTCUSD/hist")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else {
completion(nil, error ?? FetchError.unknownNetworkError)
return
}
do {
let bitcoin = try JSONDecoder().decode([BTCData].self, from: data); completion(bitcoin, nil)
//let close52 = bitcoin[51].close
//print(bitcoin)
//print(close52)
} catch let parseError {
completion(nil, parseError)
}
}
task.resume()
}
class FindArray {
var items = [BTCData]()
func findArray() {
let close2 = items[1].close
print(close2)
}
}
fetchBitcoinData() { items, error in
guard let items = items,
error == nil else {
print(error ?? "Unknown error")
return
}
let call = FindArray()
call.items = items
call.findArray()
}
EDIT 2: Solved it with [BTCData](). var items : [BTCData] = [] works too
To decode an array of arrays into a struct with Decodable you have to use unkeyedContainer. Since there is no dictionary CodingKeys are useless.
struct BTCData : Decodable {
let timestamp : Int
let open, close, high, low, volume : Double
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
timestamp = try container.decode(Int.self)
open = try container.decode(Double.self)
close = try container.decode(Double.self)
high = try container.decode(Double.self)
low = try container.decode(Double.self)
volume = try container.decode(Double.self)
}
}
You don't have to change your JSONDecoder() line.
...
if let bitcoin = try JSONDecoder().decode([BTCData].self, from: data).first {
print(bitcoin)
completion(bitcoin, nil)
}
Just by adding two lines it's even possible to decode the timestamp into a Date value
struct BTCData : Decodable {
let timestamp : Date
let open, close, high, low, volume : Double
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
timestamp = try container.decode(Date.self)
...
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .millisecondsSince1970
if let bitcoin = try decoder.decode([BTCData].self, from: data).first {
print(bitcoin)
completion(bitcoin, nil)
}
To decode the array and get a value at specific index
do {
let bitcoins = try JSONDecoder().decode([BTCData].self, from: data)
let close52 = bitcoins[51].close
print(close52)
...
You need to use JSONSerialization and cast to [[NSNumber]] to get the result needed
UPDATE
Checking this https://docs.bitfinex.com/v2/reference#rest-public-candles I think this is what you are searching for
Try using this
func fetchBitcoinData(completion: #escaping ([BTCData]?, Error?) -> Void) {
let url = URL(string: "https://api.bitfinex.com/v2/candles/trade:30m:tBTCUSD/hist")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else { return }
do {
if let array = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[NSNumber]]{
var arrayOfCoinData : [BTCData] = []
for currentArray in array{
arrayOfCoinData.append(BTCData(close: currentArray[2].doubleValue, high: currentArray[3].doubleValue, low: currentArray[4].doubleValue))
}
debugPrint(arrayOfCoinData)
completion(arrayOfCoinData, nil)
}
} catch {
print(error)
completion(nil, error)
}
}
task.resume()
}
Log Result
[BitcoinApiExample.BTCData(close: 7838.8999999999996,...]

Swift - AWS S3 Upload Image from Photo Library and download it

I've looked many amazon docs but didn't find enough information to upload and download images to S3 using Swift.
How can I do that?
After doing many research I've got this working,
import AWSS3
import AWSCore
Upload:
I assume you have implemented UIImagePickerControllerDelegate already.
Step 1:
Create variable for holding url:
var imageURL = NSURL()
Create upload completion handler obj:
var uploadCompletionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
Step 2: Get Image URL from imagePickerController(_:didFinishPickingMediaWithInfo:):
Set value of imageURL in this delegate method:
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]){
//getting details of image
let uploadFileURL = info[UIImagePickerControllerReferenceURL] as! NSURL
let imageName = uploadFileURL.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first! as String
// getting local path
let localPath = (documentDirectory as NSString).stringByAppendingPathComponent(imageName!)
//getting actual image
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let data = UIImagePNGRepresentation(image)
data!.writeToFile(localPath, atomically: true)
let imageData = NSData(contentsOfFile: localPath)!
imageURL = NSURL(fileURLWithPath: localPath)
picker.dismissViewControllerAnimated(true, completion: nil)
}
Step 3: Call this uploadImage method after imageURL set to Upload Image to your bucket:
func uploadImage(){
//defining bucket and upload file name
let S3BucketName: String = "bucketName"
let S3UploadKeyName: String = "public/testImage.jpg"
let expression = AWSS3TransferUtilityUploadExpression()
expression.uploadProgress = {(task: AWSS3TransferUtilityTask, bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) in
dispatch_async(dispatch_get_main_queue(), {
let progress = Float(totalBytesSent) / Float(totalBytesExpectedToSend)
print("Progress is: \(progress)")
})
}
self.uploadCompletionHandler = { (task, error) -> Void in
dispatch_async(dispatch_get_main_queue(), {
if ((error) != nil){
print("Failed with error")
print("Error: \(error!)");
}
else{
print("Sucess")
}
})
}
let transferUtility = AWSS3TransferUtility.defaultS3TransferUtility()
transferUtility.uploadFile(imageURL, bucket: S3BucketName, key: S3UploadKeyName, contentType: "image/jpeg", expression: expression, completionHander: uploadCompletionHandler).continueWithBlock { (task) -> AnyObject! in
if let error = task.error {
print("Error: \(error.localizedDescription)")
}
if let exception = task.exception {
print("Exception: \(exception.description)")
}
if let _ = task.result {
print("Upload Starting!")
}
return nil;
}
}
Download:
func downloadImage(){
var completionHandler: AWSS3TransferUtilityDownloadCompletionHandlerBlock?
let S3BucketName: String = "bucketName"
let S3DownloadKeyName: String = "public/testImage.jpg"
let expression = AWSS3TransferUtilityDownloadExpression()
expression.downloadProgress = {(task: AWSS3TransferUtilityTask, bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) in
dispatch_async(dispatch_get_main_queue(), {
let progress = Float(totalBytesSent) / Float(totalBytesExpectedToSend)
print("Progress is: \(progress)")
})
}
completionHandler = { (task, location, data, error) -> Void in
dispatch_async(dispatch_get_main_queue(), {
if ((error) != nil){
print("Failed with error")
print("Error: \(error!)")
}
else{
//Set your image
var downloadedImage = UIImage(data: data!)
}
})
}
let transferUtility = AWSS3TransferUtility.defaultS3TransferUtility()
transferUtility.downloadToURL(nil, bucket: S3BucketName, key: S3DownloadKeyName, expression: expression, completionHander: completionHandler).continueWithBlock { (task) -> AnyObject! in
if let error = task.error {
print("Error: \(error.localizedDescription)")
}
if let exception = task.exception {
print("Exception: \(exception.description)")
}
if let _ = task.result {
print("Download Starting!")
}
return nil;
}
}
Ref. for upload image
Ref. for download image
Many thanks to jzorz
If all you want is to download the image, this is a much more concise and correct way to do it:
func downloadImage(bucketName: String, fileName: String, completion: (image: UIImage?, error: NSError?) -> Void) {
let transferUtility = AWSS3TransferUtility.defaultS3TransferUtility()
transferUtility.downloadDataFromBucket(bucketName, key: fileName, expression: nil) { (task, url, data, error) in
var resultImage: UIImage?
if let data = data {
resultImage = UIImage(data: data)
}
completion(image: resultImage, error: error)
}
}
func uploadFile(with resource: String, type: String) {
let key = "\(resource).\(type)"
let localImagePath = Bundle.main.path(forResource: resource, ofType: type)
let localImageUrl = URL(fileURLWithPath: localImagePath!)
let transferManager1 = AWSS3TransferUtility.default()
let expression = AWSS3TransferUtilityUploadExpression()
self.uploadCompletionHandler = { (task, error) -> Void in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2, execute: {
if ((error) != nil){
print("Failed with error")
print("Error: \(error!)");
}
else{
print("Sucess")
}
})
}
let transferUtility = AWSS3TransferUtility.default()
transferUtility.uploadFile(localImageUrl, bucket: "", key: key, contentType: "video/mov", expression: expression, completionHandler: uploadCompletionHandler).continueWith { (task) -> AnyObject? in
if let error = task.error {
print("Error: \(error.localizedDescription)")
}
if let _ = task.result {
print("Upload Starting!")
}
return nil;
}
}
#IBAction func uplaodVideo(){
uploadFile(with: "random", type: "mov")
}
The above answers were really helpful to me, but they're quite outdated due to a lot of the nomenclature being changed. So I'm providing an updated version of the answer based on the latest Swift frameworks.
Image Picker Controller:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
//getting details of image
let uploadFileURL = info[UIImagePickerController.InfoKey.referenceURL] as! NSURL
let imageName = uploadFileURL.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! as String
// getting local path
let localPath = (documentDirectory as NSString).appendingPathComponent(imageName!)
//getting actual image
let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
let data = image.pngData()
let imageData = image.pngData()! as NSData
let photoURL = NSURL(fileURLWithPath: localPath)
self.uploadFileURL = photoURL
self.uploadImage(inputData: imageData)
do {
let result = try data?.write(to: photoURL as URL, options: .atomic)
} catch let error {
print(error)
}
picker.dismiss(animated: true, completion: nil)
}
Upload Image:
A quick note on upload image. I hashed my filenames. This is not a necessary step, but I highly recommend to do so in the production stage just to ensure no filenames conflict in your S3 bucket.
func uploadImage(inputData: NSData) {
//defining bucket and upload file name
let S3BucketName: String = "your_bucket_name"
let hashed = SHA256.hash(data: inputData)
let S3UploadKeyName: String = hashed.compactMap { String(format: "%02x", $0) }.joined()
let expression = AWSS3TransferUtilityUploadExpression()
expression.progressBlock = {(task: AWSS3TransferUtilityTask, progress: Progress) in
print(progress.fractionCompleted)
}
self.uploadCompletionHandler = { (task, error) -> Void in
DispatchQueue.main.async(execute: {
if ((error) != nil){
print("Failed with error")
print("Error: \(error!)")
}
else{
print("Success")
}
})
}
let transferUtility = AWSS3TransferUtility.default()
transferUtility.uploadFile(self.uploadFileURL! as URL, bucket: S3BucketName, key: S3UploadKeyName, contentType: "image/jpeg", expression: expression, completionHandler: uploadCompletionHandler).continueWith { (task) -> AnyObject? in
if let error = task.error {
print("Error: \(error.localizedDescription)")
}
if let _ = task.result {
print("Upload Starting!")
// Do something with uploadTask.
}
return nil
}
}

Resources