AWS Mobile
Developer Guide

Add User File Storage to Your Mobile App with Amazon S3

Important

The following content applies if you are already using the AWS Mobile Hub to configure your backend. If you are building a new mobile or web app, or you're adding cloud capabilities to your existing app, use the new AWS Amplify CLI instead. With the new Amplify CLI, you can use all of the features described in Announcing the AWS Amplify CLI toolchain, including AWS CloudFormation functionality that provides additional workflows.

Overview

Enable your app to store and retrieve user files from cloud storage with the permissions model that suits your purpose. Mobile Hub User File Storage deploys and configures cloud storage buckets using Amazon Simple Storage Service (Amazon S3).

Set Up Your Backend

  1. Complete the Get Started steps before your proceed.

    If you want to integrate an Amazon S3 bucket that you have already configured, go to Integrate an Existing Bucket.

  2. Enable User File Storage: Open your project in Mobile Hub and choose the User File Storage tile to enable the feature.

  3. When the operation is complete, an alert will pop up saying "Your Backend has been updated", prompting you to download the latest copy of the cloud configuration file. If you're done configuring the feature, choose the banner to return to the project details page.

  4. From the project detail page, every app that needs to be updated with the latest cloud configuration file will have a flashing Integrate button. Choose the button to enter the integrate wizard.

  5. Update your app with the latest copy of the cloud configuration file. Your app now references the latest version of your backend. Choose Next and follow the User File Storage documentation below to connect to your backend.

Connect to Your Backend

Make sure to complete the add-aws-mobile-user-sign-in-backend-setup steps before using the integration steps on this page.

To add User File Storage to your app

Android - JavaAndroid - KotliniOS - Swift
Android - Java

Set up AWS Mobile SDK components as follows:

  1. Add the following to app/build.gradle (Module:app):

    dependencies { implementation 'com.amazonaws:aws-android-sdk-s3:2.7.+' implementation 'com.amazonaws:aws-android-sdk-cognito:2.7.+' }

    Perform a Gradle Sync to download the AWS Mobile SDK components into your app

  2. Add the following to AndroidManifest.xml:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application ... > <!- Other manifest / application items . . . -> <service android:name="com.amazonaws.mobileconnectors.s3.transferutility.TransferService" android:enabled="true" /> </application>
  3. For each Activity where you make calls to perform user file storage operations, import the following packages.

    import com.amazonaws.mobileconnectors.s3.transferutility.*;
Android - Kotlin

Set up AWS Mobile SDK components as follows:

  1. Add the following to app/build.gradle:

    apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' dependencies { implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'com.amazonaws:aws-android-sdk-s3:2.7.+' implementation 'com.amazonaws:aws-android-sdk-cognito:2.7.+' }

    Perform a Gradle Sync to download the AWS Mobile SDK components into your app

  2. Add the following to AndroidManifest.xml:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application ... > <!- Other manifest / application items . . . -> <service android:name="com.amazonaws.mobileconnectors.s3.transferutility.TransferService" android:enabled="true" /> </application>
  3. For each Activity where you make calls to perform user file storage operations, import the following packages.

    import com.amazonaws.mobileconnectors.s3.transferutility.*;
iOS - Swift

Set up AWS Mobile SDK components as follows:

  1. Add the following to Podfile that you configure to install the AWS Mobile SDK:

    platform :ios, '9.0' target :'YOUR-APP-NAME' do use_frameworks! pod 'AWSS3', '~> 2.6.13' # For file transfers pod 'AWSCognito', '~> 2.6.13' #For data sync # other pods . . . end

    Run pod install --repo-update before you continue.

    If you encounter an error message that begins "[!] Failed to connect to GitHub to update the CocoaPods/Specs . . .", and your internet connectivity is working, you may need to update openssl and Ruby.

  2. Add the following imports to the classes that perform user file storage operations:

    import AWSCore import AWSS3
  3. Add the following code to your AppDelegate to establish a run-time connection with AWS Mobile.

    import UIKit import AWSMobileClient @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { return AWSMobileClient.sharedInstance().interceptApplication(application, didFinishLaunchingWithOptions: launchOptions) } }

Upload a File

Android - JavaAndroid - KotliniOS - Swift
Android - Java

To upload a file to an Amazon S3 bucket, use AWSMobileClient to get the AWSConfiguration and AWSCredentialsProvider, then create the TransferUtility object. AWSMobileClient expects an activity context for resuming an authenticated session and creating the credentials provider.

The following example shows using the TransferUtility in the context of an Activity. If you are creating TransferUtility from an application context, you can construct the AWSCredentialsProvider and pass it into TransferUtility to use in forming the AWSConfiguration object. TransferUtility will check the size of file being uploaded and will automatically switch over to using multi-part uploads if the file size exceeds 5 MB.

import android.app.Activity; import android.util.Log; import com.amazonaws.mobile.client.AWSMobileClient; import com.amazonaws.mobileconnectors.s3.transferutility.TransferUtility; import com.amazonaws.mobileconnectors.s3.transferutility.TransferState; import com.amazonaws.mobileconnectors.s3.transferutility.TransferObserver; import com.amazonaws.mobileconnectors.s3.transferutility.TransferListener; import com.amazonaws.services.s3.AmazonS3Client; import java.io.File; public class YourActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { AWSMobileClient.getInstance().initialize(this).execute(); uploadWithTransferUtility(); } public void uploadWithTransferUtility() { TransferUtility transferUtility = TransferUtility.builder() .context(getApplicationContext()) .awsConfiguration(AWSMobileClient.getInstance().getConfiguration()) .s3Client(new AmazonS3Client(AWSMobileClient.getInstance().getCredentialsProvider())) .build(); TransferObserver uploadObserver = transferUtility.upload( "s3Folder/s3Key.txt", new File("/path/to/file/localFile.txt")); // Attach a listener to the observer to get state update and progress notifications uploadObserver.setTransferListener(new TransferListener() { @Override public void onStateChanged(int id, TransferState state) { if (TransferState.COMPLETED == state) { // Handle a completed upload. } } @Override public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) { float percentDonef = ((float) bytesCurrent / (float) bytesTotal) * 100; int percentDone = (int)percentDonef; Log.d("YourActivity", "ID:" + id + " bytesCurrent: " + bytesCurrent + " bytesTotal: " + bytesTotal + " " + percentDone + "%"); } @Override public void onError(int id, Exception ex) { // Handle errors } }); // If you prefer to poll for the data, instead of attaching a // listener, check for the state and progress in the observer. if (TransferState.COMPLETED == uploadObserver.getState()) { // Handle a completed upload. } Log.d("YourActivity", "Bytes Transferrred: " + uploadObserver.getBytesTransferred()); Log.d("YourActivity", "Bytes Total: " + uploadObserver.getBytesTotal()); } }
Android - Kotlin

To upload a file to an Amazon S3 bucket, use AWSMobileClient to get the AWSConfiguration and AWSCredentialsProvider, then create the TransferUtility object. AWSMobileClient expects an activity context for resuming an authenticated session and creating the credentials provider.

The following example shows using the TransferUtility in the context of an Activity.

If you are creating TransferUtility from an application context, you can construct the AWSCredentialsProvider and pass it into TransferUtility to use in forming the AWSConfiguration object. TransferUtility will check the size of file being uploaded and will automatically switch over to using multi-part uploads if the file size exceeds 5 MB.

import android.os.Bundle import android.support.v7.app.AppCompatActivity import android.util.Log import com.amazonaws.AmazonServiceException import com.amazonaws.mobile.client.AWSMobileClient import com.amazonaws.mobileconnectors.s3.transferutility.TransferListener import com.amazonaws.mobileconnectors.s3.transferutility.TransferState import com.amazonaws.mobileconnectors.s3.transferutility.TransferUtility import com.amazonaws.services.s3.AmazonS3Client import kotlinx.android.synthetic.main.activity_main.* import java.io.File; class YourActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) AWSMobileClient.getInstance().initialize(this).execute() uploadWithTransferUtility() } fun uploadWithTransferUtility() { val transferUtility = TransferUtility.builder() .context(this.applicationContext) .awsConfiguration(AWSMobileClient.getInstance().configuration) .s3Client(AmazonS3Client(AWSMobileClient.getInstance().credentialsProvider)) .build() val uploadObserver = transferUtility.upload("s3folder/s3key.txt", File("/path/to/localfile.txt")) // Attach a listener to the observer uploadObserver.setTransferListener(object : TransferListener { override fun onStateChanged(id: Int, state: TransferState) { if (state == TransferState.COMPLETED) { // Handle a completed upload } } override fun onProgressChanged(id: Int, current: Long, total: Long) { val done = (((current.toDouble() / total) * 100.0).toInt()) Log.d(LOG_TAG, "UPLOAD - - ID: $id, percent done = $done") } override fun onError(id: Int, ex: Exception) { Log.d(LOG_TAG, "UPLOAD ERROR - - ID: $id - - EX: ${ex.message.toString()}") } }) // If you prefer to long-poll for updates if (uploadObserver.state == TransferState.COMPLETED) { /* Handle completion */ } val bytesTransferred = uploadObserver.bytesTransferred } }
iOS - Swift

The following example shows how to upload a file to an Amazon S3 bucket.

func uploadData() { let data: Data = Data() // Data to be uploaded let expression = AWSS3TransferUtilityUploadExpression() expression.progressBlock = {(task, progress) in DispatchQueue.main.async(execute: { // Do something e.g. 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: "YourBucket", key: "YourFileName", contentType: "text/plain", expression: expression, completionHandler: completionHandler).continueWith { (task) -> AnyObject! in if let error = task.error { print("Error: \(error.localizedDescription)") } if let _ = task.result { // Do something with uploadTask. } return nil; } }

Download a File

Android - JavaAndroid - KotliniOS - Swift
Android - Java

To download a file from an Amazon S3 bucket, use AWSMobileClient to get the AWSConfiguration and AWSCredentialsProvider to create the TransferUtility object. AWSMobileClient expects an activity context for resuming an authenticated session and creating the AWSCredentialsProvider.

The following example shows using the TransferUtility in the context of an Activity. If you are creating TransferUtility from an application context, you can construct the AWSCredentialsProvider and pass it into TransferUtility to use in forming the AWSConfiguration object.

import android.app.Activity; import android.util.Log; import com.amazonaws.mobile.client.AWSMobileClient; import com.amazonaws.mobileconnectors.s3.transferutility.TransferUtility; import com.amazonaws.mobileconnectors.s3.transferutility.TransferState; import com.amazonaws.mobileconnectors.s3.transferutility.TransferObserver; import com.amazonaws.mobileconnectors.s3.transferutility.TransferListener; import com.amazonaws.services.s3.AmazonS3Client; import java.io.File; public class YourActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { AWSMobileClient.getInstance().initialize(this).execute(); downloadWithTransferUtility(); } private void downloadWithTransferUtility() { TransferUtility transferUtility = TransferUtility.builder() .context(getApplicationContext()) .awsConfiguration(AWSMobileClient.getInstance().getConfiguration()) .s3Client(new AmazonS3Client(AWSMobileClient.getInstance().getCredentialsProvider())) .build(); TransferObserver downloadObserver = transferUtility.download( "s3Folder/s3Key.txt", new File("/path/to/file/localFile.txt")); // Attach a listener to the observer to get state update and progress notifications downloadObserver.setTransferListener(new TransferListener() { @Override public void onStateChanged(int id, TransferState state) { if (TransferState.COMPLETED == state) { // Handle a completed upload. } } @Override public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) { float percentDonef = ((float)bytesCurrent/(float)bytesTotal) * 100; int percentDone = (int)percentDonef; Log.d(LOG_TAG, " ID:" + id + " bytesCurrent: " + bytesCurrent + " bytesTotal: " + bytesTotal + " " + percentDone + "%"); } @Override public void onError(int id, Exception ex) { // Handle errors } }); // If you prefer to poll for the data, instead of attaching a // listener, check for the state and progress in the observer. if (TransferState.COMPLETED == downloadObserver.getState()) { // Handle a completed upload. } Log.d(LOG_TAG, "Bytes Transferrred: " + downloadObserver.getBytesTransferred()); Log.d(LOG_TAG, "Bytes Total: " + downloadObserver.getBytesTotal()); } }
Android - Kotlin

To download a file from an Amazon S3 bucket, use AWSMobileClient to get the AWSConfiguration and AWSCredentialsProvider to create the TransferUtility object. AWSMobileClient expects an activity context for resuming an authenticated session and creating the AWSCredentialsProvider.

The following example shows using the TransferUtility in the context of an Activity. If you are creating TransferUtility from an application context, you can construct the AWSCredentialsProvider and pass it into TransferUtility to use in forming the AWSConfiguration object.

import android.app.Activity; import android.util.Log; import com.amazonaws.mobile.client.AWSMobileClient; import com.amazonaws.mobileconnectors.s3.transferutility.TransferUtility; import com.amazonaws.mobileconnectors.s3.transferutility.TransferState; import com.amazonaws.mobileconnectors.s3.transferutility.TransferObserver; import com.amazonaws.mobileconnectors.s3.transferutility.TransferListener; import com.amazonaws.services.s3.AmazonS3Client; import java.io.File; class YourActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_your) AWSMobileClient.getInstance().initialize(this).execute() donwloadWithTransferUtility() } private fun downloadWithTransferUtility() { val transferUtility = TransferUtility.builder() .context(applicationContext) .awsConfiguration(AWSMobileClient.getInstance().configuration) .s3Client(AmazonS3Client(AWSMobileClient.getInstance().credentialsProvider)) .build() val downloadObserver = transferUtility.download( "s3folder/s3key.txt", File("/path/to/file/localfile.txt")) // Attach a listener to get state updates downloadObserver.setTransferListener(object : TransferListener { override fun onStateChanged(id: Int, state: TransferState) { if (state == TransferState.COMPLETED) { // Handle a completed upload. } } override fun onProgressChanged(id: Int, current: Long, total: Long) { try { val done = (((current.toDouble() / total) * 100.0).toInt()) //as Int Log.d(LOG_TAG, "DOWNLOAD - - ID: $id, percent done = $done") } catch (e: Exception) { Log.e(LOG_TAG, "Trouble calculating progress percent", e) } } override fun onError(id: Int, ex: Exception) { Log.d(LOG_TAG, "DOWNLOAD ERROR - - ID: $id - - EX: ${ex.message.toString()}") } }) // If you prefer to poll for the data, instead of attaching a // listener, check for the state and progress in the observer. if (downloadObserver.state == TransferState.COMPLETED) { // Handle a completed upload. } Log.d(LOG_TAG, "Bytes Transferrred: ${downloadObserver.bytesTransferred}"); } }
iOS - Swift

The following example shows how to download a file from an Amazon S3 bucket.

func downloadData() { let expression = AWSS3TransferUtilityDownloadExpression() expression.progressBlock = {(task, progress) in DispatchQueue.main.async(execute: { // Do something e.g. Update a progress bar. }) } var completionHandler: AWSS3TransferUtilityDownloadCompletionHandlerBlock? completionHandler = { (task, URL, data, error) -> Void in DispatchQueue.main.async(execute: { // Do something e.g. Alert a user for transfer completion. // On failed downloads, `error` contains the error object. }) } let transferUtility = AWSS3TransferUtility.default() transferUtility.downloadData( fromBucket: "YourBucket", key: "YourFileName", expression: expression, completionHandler: completionHandler ).continueWith { (task) -> AnyObject! in if let error = task.error { print("Error: \(error.localizedDescription)") } if let _ = task.result { // Do something with downloadTask. } return nil; } }

Next Steps