简体   繁体   中英

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
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM