AWS S3 Swift – Upload Image from camera or photolibrary

Using the s3transferutility we will upload images from your camera or photo library in swift. View the source on github

In this example We will have 2 buttons – Camera Upload and Picture Upload.

Depending on what is selected as the data source (camera or photo library) it will upload the file accordingly. If you use the camera button you will notice that we will have to create a temp directory when uploading the image, since there is no asset location for it on the device.

You can find more info in the aws sdk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
//
//  PictureViewController.swift
//
//
//  Created by Jose Deras on 12/30/15.
//  Copyright © 2015 Jose Deras. All rights reserved.
//
 
import UIKit
import AWSMobileAnalytics
import AWSCognito
import AWSS3
import AWSCore
import Photos
import MobileCoreServices
 
 
 
 
class PictureViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
     
    @IBOutlet weak var progressView: UIProgressView!
     
 
    @IBOutlet weak var imageView: UIImageView!
     
    @IBAction func openCameraButton(sender: AnyObject) {
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) {
            let camImagePicker = UIImagePickerController()
            camImagePicker.delegate = self
            camImagePicker.sourceType = UIImagePickerControllerSourceType.Camera;
            camImagePicker.allowsEditing = false
            self.presentViewController(camImagePicker, animated: true, completion: nil)
        }
    }
     
     
    @IBAction func openPhotoLibrary(sender: AnyObject) {
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) {
            let imagePicker = UIImagePickerController()
            imagePicker.delegate = self
            imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary;
            imagePicker.allowsEditing = true
            self.presentViewController(imagePicker, animated: true, completion: nil)
        }
    }
 
     
     
    
     
    //handles upload
    var uploadCompletionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
     
    var uploadFileURL: NSURL?
     
 
    override func viewDidLoad() {
        super.viewDidLoad()
         
 
 
        //setting progress bar to 0
        self.progressView.progress = 0.0;
        
      
 
         
    }
 
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
     
     
     
    //begin upload from photo library
 
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
       
        //first run if its coming from photo album
        if(picker.sourceType == UIImagePickerControllerSourceType.PhotoLibrary)
        {
             
        //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)!
        let photoURL = NSURL(fileURLWithPath: localPath)
        
        // let imageWithData = UIImage(data: imageData)!
         
         
        //defining bucket and upload file name
        let S3BucketName: String = "bucketNAme"
        let S3UploadKeyName: String = "test_libarayUpload.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)
                self.progressView.progress = progress
                // self.statusLabel.text = "Uploading..."
                NSLog("Progress is: %f",progress)
            })
        }
         
        self.uploadCompletionHandler = { (task, error) -> Void in
            dispatch_async(dispatch_get_main_queue(), {
                if ((error) != nil){
                    NSLog("Failed with error")
                    NSLog("Error: %@",error!);
                    //    self.statusLabel.text = "Failed"
                }
                else if(self.progressView.progress != 1.0) {
                    //    self.statusLabel.text = "Failed"
                    NSLog("Error: Failed - Likely due to invalid region / filename")
                }
                else{
                    //    self.statusLabel.text = "Success"
                    NSLog("Sucess")
                }
            })
        }
         
        let transferUtility = AWSS3TransferUtility.defaultS3TransferUtility()
         
        transferUtility?.uploadFile(photoURL, bucket: S3BucketName, key: S3UploadKeyName, contentType: "image/jpeg", expression: expression, completionHander: uploadCompletionHandler).continueWithBlock { (task) -> AnyObject! in
            if let error = task.error {
                NSLog("Error: %@",error.localizedDescription);
                //  self.statusLabel.text = "Failed"
            }
            if let exception = task.exception {
                NSLog("Exception: %@",exception.description);
                //   self.statusLabel.text = "Failed"
            }
            if let _ = task.result {
                // self.statusLabel.text = "Generating Upload File"
                NSLog("Upload Starting!")
                // Do something with uploadTask.
            }
             
            return nil;
        }
         
            //end if photo library upload
        self.dismissViewControllerAnimated(true, completion: nil);
         
        }
             
             
            //second check if its coming from camera
        else if(picker.sourceType == UIImagePickerControllerSourceType.Camera)
        {
         
          //  var imageToSave: UIImage = info(UIImagePickerControllerOriginalImage) as UIImage
            var imageToSave: UIImage = info[UIImagePickerControllerOriginalImage] as! UIImage
             
            //defining bucket and upload file name
            let S3BucketName: String = "bucketName"
            //setting temp name for upload
            let S3UploadKeyName = "Test2CameraUpload.jpg"
             
            //settings temp location for image
            let imageName = NSURL.fileURLWithPath(NSTemporaryDirectory() + S3UploadKeyName).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)!
            let photoURL = NSURL(fileURLWithPath: localPath)
             
 
             
            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)
                    self.progressView.progress = progress
                    // self.statusLabel.text = "Uploading..."
                    NSLog("Progress is: %f",progress)
                })
            }
             
            self.uploadCompletionHandler = { (task, error) -> Void in
                dispatch_async(dispatch_get_main_queue(), {
                    if ((error) != nil){
                        NSLog("Failed with error")
                        NSLog("Error: %@",error!);
                        //    self.statusLabel.text = "Failed"
                    }
                    else if(self.progressView.progress != 1.0) {
                        //    self.statusLabel.text = "Failed"
                        NSLog("Error: Failed - Likely due to invalid region / filename")
                    }
                    else{
                        //    self.statusLabel.text = "Success"
                        NSLog("Sucess")
                    }
                })
            }
             
            let transferUtility = AWSS3TransferUtility.defaultS3TransferUtility()
             
            transferUtility?.uploadFile(photoURL, bucket: S3BucketName, key: S3UploadKeyName, contentType: "image/jpeg", expression: expression, completionHander: uploadCompletionHandler).continueWithBlock { (task) -> AnyObject! in
                if let error = task.error {
                    NSLog("Error: %@",error.localizedDescription);
                    //  self.statusLabel.text = "Failed"
                }
                if let exception = task.exception {
                    NSLog("Exception: %@",exception.description);
                    //   self.statusLabel.text = "Failed"
                }
                if let _ = task.result {
                    // self.statusLabel.text = "Generating Upload File"
                    NSLog("Upload Starting!")
                    // Do something with uploadTask.
                }
                 
                return nil;
            }
             
            //end if photo library upload
            self.dismissViewControllerAnimated(true, completion: nil);
             
         
 
        }
        
        else{
            NSLog("Shit fucked up yo")
        }
         
         
    }
   
 
}

13 thoughts on “AWS S3 Swift – Upload Image from camera or photolibrary”

  1. Can u pls send the project ……And my requirement is when i click the action sheet button then my image will be saved in the bucket….

  2. Hi Jose! I love your AWS swift series of articles. I’m trying to understand something: Say that your trying to make an app where users can upload pics/videos to S3. If you wanted to view pics/videos uploaded by a specific user, could you query AWS S3 in that way? So my understanding is you can store user data in AWS DynamoDB (w/Titan for graph based) and somehow link the userId attribute to media that you upload to S3?

    Thanks so much!

    1. Hi Jason. Yes that is possible. I am working on a tutorial hopefully I can get it finished soon!

  3. Hey! Great tutorial! One question though: I am having problems with my ”
    expression.uploadProgress”. The complier says “AWSS3TransferUtilityUploadExpression has not member uploadProgress”. I seem to have everything linked up in my bridging header and stuff. Any help please?

    Thanks

  4. Hi there,
    I’m having some minor issues here.. It’s this part of the command that causes it.
    “express.uploadProgress”

    Error Prompt: AWSS3TransferUtilityUploadExpression has no member ‘uploadprogress’

    Can i enquire: what are the reasons and how do i get this resolve?

    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)
    self.progressView.progress = progress
    // self.statusLabel.text = “Uploading…”
    NSLog(“Progress is: %f”,progress)
    })
    }

  5. Hi,

    I was able to compile and execute the script. The console says the upload has been a success but I do not see anything in the Amazon S3 server. Could you tell me what the cause of this problem is?

    Thanks

  6. Hi! I’m getting the following error:
    value of type ‘AWSS3TransferUtilityUploadExpression’ has no member ‘uploadProgress’.
    Do you have any idea as to why? If i comment that part, everything else works fine.

    1. Replace that line with
      let expression = AWSS3TransferUtilityUploadExpression()
      expression.progressBlock = { (task: AWSS3TransferUtilityTask, progress: NSProgress) in
      print(progress.fractionCompleted)
      }

Leave a Reply to Anooj Krishnan G Cancel reply

Your email address will not be published. Required fields are marked *