'How to download images from AWS S3 in swift?

is there a good function to download images from AWS S3 bucket? I have an access key and a secret key for permisson. The URL is thru a different database accessible. I also already imported AWSS3 and AWSCore.

I have already found a upload function:

 func uploadFile(withImage image: UIImage) {
    
    let access = "access_key"
    let secret = "secret_key"
    let credentials = AWSStaticCredentialsProvider(accessKey: access, secretKey: secret)
    let configuration = AWSServiceConfiguration(region: AWSRegionType.EUCentral1, credentialsProvider: credentials)

    AWSServiceManager.default().defaultServiceConfiguration = configuration

    let s3BucketName = "bucket_name"
    let compressedImage = image.resizedImage(newSize: CGSize(width: 80, height: 80))
    let data: Data = compressedImage.pngData()!
    let remoteName = generateRandomStringWithLength(length: 12)+"."+data.format
    print("REMOTE NAME : ",remoteName)

    let expression = AWSS3TransferUtilityUploadExpression()
    expression.progressBlock = { (task, progress) in
        DispatchQueue.main.async(execute: {
            // Update a progress bar
        })
    }

   var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
    completionHandler = { (task, error) -> Void in
        DispatchQueue.main.async(execute: {
            // Do something e.g. Alert a user for transfer completion.
            // On failed uploads, `error` contains the error object.
        })
    }

    let transferUtility = AWSS3TransferUtility.default()
    transferUtility.uploadData(data, bucket: s3BucketName, key: remoteName, contentType: "image/"+data.format, expression: expression, completionHandler: completionHandler).continueWith { (task) -> Any? in
        if let error = task.error {
            print("Error : \(error.localizedDescription)")
        }

        if task.result != nil {
            let url = AWSS3.default().configuration.endpoint.url
            let publicURL = url?.appendingPathComponent(s3BucketName).appendingPathComponent(remoteName)
            if let absoluteString = publicURL?.absoluteString {
                // Set image with URL
                print("Image URL : ",absoluteString)
            }
        }

        return nil
    }

}


Solution 1:[1]

I would not recommend to download files directly from S3 using an access and secret key.

I'd propose you do the following:

  1. Make sure the bucket is as "private" as can be.
  2. Have an API with authentication and authorisation (AWS API Gateway) that checks if the user is authenticated and permitted to download the S3 object.
  3. Generate a pre-signed download URL with that is only valid for a short period of time (15-60 minutes).
  4. Return that pre-signed download URL to your app through the API.
  5. Use the URL within your app to download the S3 object.

This way you don't have to ship username and password in your app and the bucket is closed off to the "outside" reducing the risk of accidental information leakage.


Why I wouldn't recommend using the access key and secret key:

This is a potential security issue. People that reverse engineer the app could gain access to those "static" keys and depending on the underlying IAM role do all sorts of harm. But even if you have proper IAM roles with very limited access, essentially shipping a username and password with your app is not a good idea under any circumstance. How would you "rotate" the secret if something bad happens etc.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jens