I've created two different functions for uploading PHASSets to my backend -
the uploadImageAsset() uploads all of the assets that are images:
func uploadImageAsset(asset: PHAsset, projectRef: String) {
let userID = Auth.auth().currentUser?.uid
let db = Firestore.firestore()
let dbRef = db.collection("projects").document(projectRef)
let manager = PHImageManager.default()
let option = PHImageRequestOptions()
option.isSynchronous = false
option.isNetworkAccessAllowed = true
option.resizeMode = .exact
option.version = .original
option.deliveryMode = .highQualityFormat
let imageSize = CGSize(width: asset.pixelWidth, height: asset.pixelHeight)
let uniqueImageID = NSUUID().uuidString
let storageRef = Storage.storage().reference().child("project-images").child("\(uniqueImageID).jpeg")
manager.requestImage(for: asset, targetSize: imageSize, contentMode: .aspectFill, options: option) { (image, info) in
let uploadData = image?.jpegData(compressionQuality: 0.6)
storageRef.putData(uploadData!, metadata: nil, completion: {
(metadata, error) in
if error != nil {
return
} else {
storageRef.getMetadata(completion: { (metadata, err) in
if let error = err {
print(error)
} else {
storageRef.downloadURL(completion: { (url, err) in
if let error = err {
print(error)
} else {
self.imageURLs.append((url?.absoluteString)!)
dbRef.updateData(["image": self.imageURLs], completion: { (err) in
if err != nil {
print(err)
} else {
SVProgressHUD.dismiss(withDelay: 0.3)
self.dismiss(animated: true, completion: nil)
}
})
}
})
}
})
}
})
}
}
and the uploadProjectVideos() uploads all of the assets that are videos:
func uploadVideoAsset(asset: PHAsset, projectRef: String) {
let userID = Auth.auth().currentUser?.uid
let db = Firestore.firestore()
let dbRef = db.collection("projects").document(projectRef)
let manager = PHImageManager.default()
let option = PHVideoRequestOptions()
option.isNetworkAccessAllowed = true
option.deliveryMode = PHVideoRequestOptionsDeliveryMode.highQualityFormat
manager.requestAVAsset(forVideo: asset, options: option) { (video, videoAudio, nil) in
let avurlAsset = video as! AVURLAsset
let fileURL = avurlAsset.url.absoluteString as! URL
let fileName = NSUUID().uuidString + ".mov"
let uploadTask = Storage.storage().reference().child(fileName).putFile(from: fileURL, metadata: nil, completion: { (metaData, error) in
if error != nil {
print("Failed upload of video", error)
return
}
Storage.storage().reference().child(fileName).downloadURL { (url, error) in
self.imageURLs.append("\(url)")
dbRef.updateData(["image": self.imageURLs], completion: { (err) in
if err != nil {
print(err)
} else {
SVProgressHUD.dismiss(withDelay: 0.3)
self.dismiss(animated: true, completion: nil)
}
})
}
})
}
}
When it comes to uploading images, my function for that works perfectly. However, my function for uploading videos is returning nil. Videos aren't being uploaded to the backend at all.
This is my first time working with PHAssets and Im really confused as to how I can get the video url of a phasset and upload it
You can use the requestAVAsset(forVideo:options:resultHandler:) method as shown in the documentation: https://developer.apple.com/documentation/photokit/phimagemanager/1616935-requestavasset.
And here's a little handy extension originally made by #iMHitesh Surani, updated to swift by #diegomen:
extension PHAsset {
func getURL(completionHandler : #escaping ((_ responseURL : URL?) -> Void)){
if self.mediaType == .image {
let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
return true
}
self.requestContentEditingInput(with: options, completionHandler: {(contentEditingInput: PHContentEditingInput?, info: [AnyHashable : Any]) -> Void in
completionHandler(contentEditingInput!.fullSizeImageURL as URL?)
})
} else if self.mediaType == .video {
let options: PHVideoRequestOptions = PHVideoRequestOptions()
options.version = .original
PHImageManager.default().requestAVAsset(forVideo: self, options: options, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [AnyHashable : Any]?) -> Void in
if let urlAsset = asset as? AVURLAsset {
let localVideoUrl: URL = urlAsset.url as URL
completionHandler(localVideoUrl)
} else {
completionHandler(nil)
}
})
}
}
}
Related
I'm trying to make a simple Instagram Clone App to learn more about Firebase. So far I can share Images, Comments, Likes, but when it comes to videos, the app fails to do that. I mange to upload the Videofile to the Storage, but I don't get the videoUrl to the Database. I'm grateful for suggestions.
class ShareService {
static var REF_STORAGE_POST = Storage.storage().reference().child("posts")
static func uploadDataToStorage(imageData: Data, videoUrl: URL? = nil, postText: String, imageRatio: CGFloat, onSuccess: #escaping () -> Void ) {
// 1. upload Video
if let _videoUrl = videoUrl {
self.uploadVideoToFireBaseStorage(videoUrl: _videoUrl, onSucces: { (videoUrlString) in
self.uploadImageToFireBaseStorage(data: imageData, onSucces: { (thumbnailUrlString) in
self.uploadDataToDatabase(imageUrl: thumbnailUrlString, videoUrl: videoUrlString, postText: postText, imageRatio: imageRatio, onSuccess: onSuccess)
})
})
} else {
// 2. upload image
self.uploadImageToFireBaseStorage(data: imageData, onSucces: { (imageUrlString) in
self.uploadDataToDatabase(imageUrl: imageUrlString, postText: postText, imageRatio: imageRatio, onSuccess: onSuccess)
})
}
}
fileprivate static func uploadVideoToFireBaseStorage(videoUrl: URL, onSucces: #escaping (_ videoUrl: String) -> Void) {
let videoIdString = NSUUID().uuidString
let storageRef = REF_STORAGE_POST.child(videoIdString)
print(videoUrl)
let metadata = StorageMetadata()
//specify MIME type
metadata.contentType = "video/quicktime"
if let videoUrl = NSData(contentsOf: videoUrl) as Data? {
storageRef.putData(videoUrl, metadata: metadata) { (metaData, error) in
if error != nil {
print("upload video error")
}
}
storageRef.downloadURL(completion: { (url, error) in
if error != nil {
print(error!.localizedDescription)
return
}
let videoUrlString = url?.absoluteString
onSucces(videoUrlString ?? "no video")
})
}
}
// upload image
fileprivate static func uploadImageToFireBaseStorage(data: Data, onSucces: #escaping (_ imageUrl: String) -> Void) {
let photoIdString = NSUUID().uuidString
let storageRef = REF_STORAGE_POST.child(photoIdString)
storageRef.putData(data, metadata: nil) { (metaData, error) in
if error != nil {
print("upload image error")
}
storageRef.downloadURL(completion: { (url, error) in
if error != nil {
print(error!.localizedDescription)
return
}
let imageUrlString = url?.absoluteString
onSucces(imageUrlString ?? "no image")
})
}
}
fileprivate static func uploadDataToDatabase(imageUrl: String, videoUrl: String? = nil, postText: String, imageRatio: CGFloat, onSuccess: #escaping () -> Void) {
let newPostId = PostApi.shared.REF_POSTS.childByAutoId().key
let newPostRef = PostApi.shared.REF_POSTS.child(newPostId!)
let postTime = Date().timeIntervalSince1970
print(postTime)
guard let currentUserUid = UserApi.shared.CURRENT_USER_UID else { return }
var dic = ["uid" : currentUserUid, "imageUrl" : imageUrl, "imageRatio" : imageRatio, "postText" : postText] as [String : Any]
if let _videoUrl = videoUrl {
dic["videoUrl"] = _videoUrl
}
newPostRef.setValue(dic) { (error, _) in
if error != nil {
print(error?.localizedDescription as Any)
}
// Show posts in newsfeed
FeedApi.shared.REF_NEWSFEED.child(currentUserUid).child(newPostId!).setValue(true)
// Eigene Posts markieren
PostApi.shared.REF_MY_POSTS.child(currentUserUid).child(newPostId!).setValue(true)
print("Post created")
onSuccess()
}
}
}
I am trying to save generated UIImage to Camera Roll.
I have necessary privacy string in Info.plist.
I tried couple of methods;
The error I am facing for PHPhotoLibrary is
Error Domain=com.apple.accounts Code=7 "(null)
The codes I have tried;
UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil);
The other one is;
PHPhotoLibrary.shared().savePhoto(image: image!, albumName: "AlbumName", completion: { (asset) in
if asset != nil
{
print("error")
}
})
func savePhoto(image:UIImage, albumName:String, completion:((PHAsset?)->())? = nil) {
func save() {
if let album = PHPhotoLibrary.shared().findAlbum(albumName: albumName) {
PHPhotoLibrary.shared().saveImage(image: image, album: album, completion: completion)
} else {
PHPhotoLibrary.shared().createAlbum(albumName: albumName, completion: { (collection) in
if let collection = collection {
PHPhotoLibrary.shared().saveImage(image: image, album: collection, completion: completion)
} else {
completion?(nil)
}
})
}
}
if PHPhotoLibrary.authorizationStatus() == .authorized {
save()
} else {
PHPhotoLibrary.requestAuthorization({ (status) in
if status == .authorized {
save()
}
})
}
}
// MARK: - Private
fileprivate func findAlbum(albumName: String) -> PHAssetCollection? {
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", albumName)
let fetchResult : PHFetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
guard let photoAlbum = fetchResult.firstObject else {
return nil
}
return photoAlbum
}
fileprivate func createAlbum(albumName: String, completion: #escaping (PHAssetCollection?)->()) {
var albumPlaceholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
let createAlbumRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: albumName)
albumPlaceholder = createAlbumRequest.placeholderForCreatedAssetCollection
}, completionHandler: { success, error in
if success {
guard let placeholder = albumPlaceholder else {
completion(nil)
return
}
let fetchResult = PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
guard let album = fetchResult.firstObject else {
completion(nil)
return
}
completion(album)
} else {
completion(nil)
}
})
}
fileprivate func saveImage(image: UIImage, album: PHAssetCollection, completion:((PHAsset?)->())? = nil) {
var placeholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
let createAssetRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
guard let albumChangeRequest = PHAssetCollectionChangeRequest(for: album),
let photoPlaceholder = createAssetRequest.placeholderForCreatedAsset else { return }
placeholder = photoPlaceholder
let fastEnumeration = NSArray(array: [photoPlaceholder] as [PHObjectPlaceholder])
albumChangeRequest.addAssets(fastEnumeration)
}, completionHandler: { success, error in
guard let placeholder = placeholder else {
completion?(nil)
return
}
if success {
let assets:PHFetchResult<PHAsset> = PHAsset.fetchAssets(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
let asset:PHAsset? = assets.firstObject
completion?(asset)
} else {
completion?(nil)
}
})
}
Could you please help me on figuring out this?
BR,
Erdem
I have figured it out.
The problem is I have been creating QR Image that is created with CIFilter is CIImage.
It returns error code = -1
You need to create UIImage from CGImage not CIImage
if let output = filter.outputImage?.transformed(by: transform) {
let context = CIContext()
guard let cgImage = context.createCGImage(output, from: output.extent) else { return nil }
return UIImage(cgImage: cgImage)
}
I am working on a Video sharing iOS app and using Firebase5 as backend. It allow User can choose video and send it to storage. When I tried the video cannot push to database server. Below is my code:
static func uploadVideoToFirebaseStorage(videoUrl: URL, onSuccess: #escaping (_ videoUrl: String) -> Void) {
let videoIdString = NSUUID().uuidString
//Config.STORAGE_ROOT_REF is var STORAGE_ROOT_REF = "gs://****-cdc3c.appspot.com"
let storageRef = Storage.storage().reference(forURL: Config.STORAGE_ROOT_REF).child("posts").child(videoIdString)
storageRef.putFile(from: videoUrl, metadata: nil) { (metadata, error) in
if error != nil {
ProgressHUD.showError(error!.localizedDescription)
return
}
}
storageRef.downloadURL(completion: { (url, error) in
if let error = error {
return
}else {
let videoUrl = url!.absoluteString
onSuccess(videoUrl)
}
})
}
Call this function to upload the video to firebase storage
func uploadTOFireBaseVideo(url: URL,
success : #escaping (String) -> Void,
failure : #escaping (Error) -> Void) {
let name = "\(Int(Date().timeIntervalSince1970)).mp4"
let path = NSTemporaryDirectory() + name
let dispatchgroup = DispatchGroup()
dispatchgroup.enter()
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let outputurl = documentsURL.appendingPathComponent(name)
var ur = outputurl
self.convertVideo(toMPEG4FormatForVideo: url as URL, outputURL: outputurl) { (session) in
ur = session.outputURL!
dispatchgroup.leave()
}
dispatchgroup.wait()
let data = NSData(contentsOf: ur as URL)
do {
try data?.write(to: URL(fileURLWithPath: path), options: .atomic)
} catch {
print(error)
}
let storageRef = Storage.storage().reference().child("Videos").child(name)
if let uploadData = data as Data? {
storageRef.putData(uploadData, metadata: nil
, completion: { (metadata, error) in
if let error = error {
failure(error)
}else{
let strPic:String = (metadata?.downloadURL()?.absoluteString)!
success(strPic)
}
})
}
}
Following function converts the video to mp4 format so that it can be viewed on any device either it be iOS or android
func convertVideo(toMPEG4FormatForVideo inputURL: URL, outputURL: URL, handler: #escaping (AVAssetExportSession) -> Void) {
try! FileManager.default.removeItem(at: outputURL as URL)
let asset = AVURLAsset(url: inputURL as URL, options: nil)
let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality)!
exportSession.outputURL = outputURL
exportSession.outputFileType = .mp4
exportSession.exportAsynchronously(completionHandler: {
handler(exportSession)
})
}
Call this function to upload video the firebase storage. Its working for me incase any confusion you can ask
static func upload(file: URL, completion: #escaping UploadCompletion) {
let name = "\(Int(Date().timeIntervalSince1970)).mp4"
do {
let data = try Data(contentsOf: file)
let storageRef =
Storage.storage().reference().child("Videos").child(name)
if let uploadData = data as Data? {
let metaData = StorageMetadata()
metaData.contentType = "video/mp4"
storageRef.putData(uploadData, metadata: metaData
, completion: { (metadata, error) in
if let error = error {
completion(nil, error.localizedDescription)
}else{
storageRef.downloadURL { (url, error) in
guard let downloadURL = url else {
completion(nil, error?.localizedDescription ?? "")
return
}
completion(downloadURL, nil)
}
}
})
}
}catch let error {
print(error.localizedDescription)
}
}
How can I download the image I uploaded in Firebase?
Here is how I upload my images:
func uploadProfileImage(_ image:UIImage, completion: #escaping ((_ url:URL?)->())) {
guard let uid = Auth.auth().currentUser?.uid else { return }
let storage = Storage.storage()
let storageRef = storage.reference().child("user/\(uid)")
guard let imageData = UIImageJPEGRepresentation(image, 0.75) else { return }
let metaData = StorageMetadata()
metaData.contentType = "image/jpg"
storageRef.putData(imageData, metadata: metaData) { metaData, error in
if let error = error {
print(error.localizedDescription)
return
}
storageRef.downloadURL(completion: { (url, error) in
if let _ = error{
return
}
if url != nil{
completion(url)
}
})
}
}
func saveProfile(username:String, profileImageURL:URL, completion: #escaping ((_ success:Bool)->())) {
guard let uid = Auth.auth().currentUser?.uid else { return }
let databaseRef = Database.database().reference().child("users/profile/\(uid)")
let userObject = [
"username": username,
"photoURL": profileImageURL.absoluteString ] as [String:Any]
databaseRef.setValue(userObject) { error, ref in
completion(error == nil)
}
}
But I'm not sure how I could download and display it. Any pointers?
Thank you in advance.
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
}
}