Name:
interface
Value:
Amplify has re-imagined the way frontend developers build fullstack applications. Develop and deploy without the hassle.

Page updated Oct 31, 2024

Set up Storage

In this guide, you will learn how to set up storage in your Amplify app. You will set up your backend resources, and enable listing, uploading, and downloading files.

If you have not yet created an Amplify app, visit the quickstart guide.

Amplify Storage seamlessly integrates file storage and management capabilities into frontend web and mobile apps, built on top of Amazon Simple Storage Service (Amazon S3). It provides intuitive APIs and UI components for core file operations, enabling developers to build scalable and secure file storage solutions without dealing with cloud service complexities.

Building your storage backend

First, create a file amplify/storage/resource.ts. This file will be the location where you configure your storage backend. Instantiate storage using the defineStorage function and providing a name for your storage bucket. This name is a friendly name to identify your bucket in your backend configuration. Amplify will generate a unique identifier for your app using a UUID, the name attribute is just for use in your app.

amplify/storage/resource.ts
import { defineStorage } from '@aws-amplify/backend';
export const storage = defineStorage({
name: 'amplifyTeamDrive'
});

Import your storage definition in your amplify/backend.ts file that contains your backend definition. Add storage to defineBackend.

amplify/backend.ts
import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource';
import { storage } from './storage/resource';
defineBackend({
auth,
storage
});

Now when you run npx ampx sandbox or deploy your app on Amplify, it will configure an Amazon S3 bucket where your files will be stored. Before files can be accessed in your application, you must configure storage access rules.

To deploy these changes, commit them to git and push the changes upstream. Amplify's CI/CD system will automatically pick up the changes and build and deploy the updates.

Terminal
git commit -am "add storage backend"
git push

Define File Path Access

By default, no users or other project resources have access to any files in the storage bucket. Access must be explicitly granted within defineStorage using the access callback.

The access callback returns an object where each key in the object is a file path and each value in the object is an array of access rules that apply to that path.

The following example shows you how you can set up your file storage structure for a generic photo sharing app. Here,

  1. Guests have access to see all profile pictures and only the users that uploaded the profile picture can replace or delete them. Users are identified by their Identity Pool ID in this case i.e. identityID.
  2. There's also a general pool where all users can submit pictures.

Learn more about customizing access to file path.

amplify/storage/resource.ts
export const storage = defineStorage({
name: 'amplifyTeamDrive',
access: (allow) => ({
'profile-pictures/{entity_id}/*': [
allow.guest.to(['read']),
allow.entity('identity').to(['read', 'write', 'delete'])
],
'picture-submissions/*': [
allow.authenticated.to(['read','write']),
allow.guest.to(['read', 'write'])
],
})
});

Configure additional storage buckets

Amplify Storage gives you the flexibility to configure your backend to automatically provision and manage multiple storage resources.

You can define additional storage buckets by using the same defineStorage function and providing a unique, descriptive name to identify the storage bucket. You can pass this name to the storage APIs to specify the bucket you want to perform the action to. Ensure that this name attribute is unique across the defined storage buckets in order to reliably identify the correct bucket and prevent conflicts.

It's important to note that if additional storage buckets are defined one of them must be marked as default with the isDefault flag.

amplify/storage/resource.ts
export const firstBucket = defineStorage({
name: 'firstBucket',
isDefault: true, // identify your default storage bucket (required)
});
export const secondBucket = defineStorage({
name: 'secondBucket',
access: (allow) => ({
'private/{entity_id}/*': [
allow.entity('identity').to(['read', 'write', 'delete'])
]
})
})

Add additional storage resources to the backend definition.

amplify/backend.ts
import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource';
import { firstBucket, secondBucket } from './storage/resource';
defineBackend({
auth,
firstBucket,
secondBucket
});

Storage bucket client usage

Additional storage buckets can be referenced from application code by passing the bucket option to Amplify Storage APIs. You can provide a target bucket's name assigned in Amplify Backend.

StorageBucket secondBucket = StorageBucket.fromOutputs("secondBucket");
StorageDownloadFileOptions options = StorageDownloadFileOptions.builder().bucket(secondBucket).build();
Amplify.Storage.downloadFile(
StoragePath.fromString("public/example"),
new File(getApplicationContext().getFilesDir() + "/download.txt"),
options,
result -> Log.i("MyAmplifyApp", "Successfully downloaded: " + result.getFile().getName()),
error -> Log.e("MyAmplifyApp", "Download Failure", error)
);
val secondBucket = StorageBucket.fromOutputs("secondBucket")
val options = StorageDownloadFileOptions.builder().bucket(secondBucket).build()
val file = File("${applicationContext.filesDir}/download.txt")
Amplify.Storage.downloadFile(StoragePath.fromString("public/example"), file, option,
{ Log.i("MyAmplifyApp", "Successfully downloaded: ${it.file.name}") },
{ Log.e("MyAmplifyApp", "Download Failure", it) }
)
val secondBucket = StorageBucket.fromOutputs("secondBucket")
val options = StorageDownloadFileOptions.builder().bucket(secondBucket).build()
val file = File("${applicationContext.filesDir}/download.txt")
val download = Amplify.Storage.downloadFile(StoragePath.fromString("public/example"), file, options)
try {
val fileName = download.result().file.name
Log.i("MyAmplifyApp", "Successfully downloaded: $fileName")
} catch (error: StorageException) {
Log.e("MyAmplifyApp", "Download Failure", error)
}
StorageBucket secondBucket = StorageBucket.fromOutputs("secondBucket");
StorageDownloadFileOptions options = StorageDownloadFileOptions.builder().bucket(secondBucket).build();
RxProgressAwareSingleOperation<StorageDownloadFileResult> download =
RxAmplify.Storage.downloadFile(
StoragePath.fromString("public/example"),
new File(getApplicationContext().getFilesDir() + "/download.txt"),
options
);
download
.observeResult()
.subscribe(
result -> Log.i("MyAmplifyApp", "Successfully downloaded: " + result.getFile().getName()),
error -> Log.e("MyAmplifyApp", "Download Failure", error)
);

Alternatively, you can also pass in an object by specifying the bucket name and region from the console. See each Amplify Storage API page for additional usage examples.

BucketInfo bucketInfo = new BucketInfo("second-bucket-name-from-console", "us-east-2");
StorageBucket secondBucket = StorageBucket.fromBucketInfo(bucketInfo);
StorageDownloadFileOptions options = StorageDownloadFileOptions.builder().bucket(secondBucket).build();
Amplify.Storage.downloadFile(
StoragePath.fromString("public/example"),
new File(getApplicationContext().getFilesDir() + "/download.txt"),
options,
result -> Log.i("MyAmplifyApp", "Successfully downloaded: " + result.getFile().getName()),
error -> Log.e("MyAmplifyApp", "Download Failure", error)
);
val bucketInfo = BucketInfo("second-bucket-name-from-console", "us-east-2")
val secondBucket = StorageBucket.fromBucketInfo(bucketInfo)
val options = StorageDownloadFileOptions.builder().bucket(secondBucket).build()
val file = File("${applicationContext.filesDir}/download.txt")
Amplify.Storage.downloadFile(StoragePath.fromString("public/example"), file, options,
{ Log.i("MyAmplifyApp", "Successfully downloaded: ${it.file.name}") },
{ Log.e("MyAmplifyApp", "Download Failure", it) }
)
val bucketInfo = BucketInfo("second-bucket-name-from-console", "us-east-2")
val secondBucket = StorageBucket.fromBucketInfo(bucketInfo)
val options = StorageDownloadFileOptions.builder().bucket(secondBucket).build()
val file = File("${applicationContext.filesDir}/download.txt")
val download = Amplify.Storage.downloadFile(StoragePath.fromString("public/example"), file, options)
try {
val fileName = download.result().file.name
Log.i("MyAmplifyApp", "Successfully downloaded: $fileName")
} catch (error: StorageException) {
Log.e("MyAmplifyApp", "Download Failure", error)
}
BucketInfo bucketInfo = new BucketInfo("second-bucket-name-from-console", "us-east-2");
StorageBucket secondBucket = StorageBucket.fromBucketInfo(bucketInfo);
StorageDownloadFileOptions options = StorageDownloadFileOptions.builder().bucket(secondBucket).build();
RxProgressAwareSingleOperation<StorageDownloadFileResult> download =
RxAmplify.Storage.downloadFile(
StoragePath.fromString("public/example"),
new File(getApplicationContext().getFilesDir() + "/download.txt"),
options,
);
download
.observeResult()
.subscribe(
result -> Log.i("MyAmplifyApp", "Successfully downloaded: " + result.getFile().getName()),
error -> Log.e("MyAmplifyApp", "Download Failure", error)
);

Connect your app code to the storage backend

The Amplify Storage library provides client APIs that connect to the backend resources you defined.

Prerequisites

  • An Android application targeting Android API level 24 (Android 7.0) or above
    • For a full example of creating Android project, please follow the quickstart guide

Install the Amplify library

Expand Gradle Scripts, open build.gradle (Module: app). You will already have configured Amplify by following the steps in the quickstart guide.

Add these libraries into the dependencies block:

app/build.gradle.kts
android {
compileOptions {
// Support for Java 8 features
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
dependencies {
// Amplify API dependencies
implementation("com.amplifyframework:aws-storage-s3:ANDROID_VERSION")
implementation("com.amplifyframework:aws-auth-cognito:ANDROID_VERSION")
// ... other dependencies
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3")
}

aws-auth-cognito is used to provide authentication for Amazon S3.

Click Sync Now.

Configure Amplify in your project

Initialize Amplify Storage by calling Amplify.addPlugin(). To complete initialization, call Amplify.configure().

Add the following code to your onCreate() method in your application class:

Before calling the Amplify.configure function, make sure to either download the amplify_outputs.json file from the console, or generate it with the following command:

Terminal
npx ampx generate outputs --app-id <app-id> --branch main --out-dir app/src/main/res/raw

Next, be sure the file you generated or downloaded is in the appropriate resource directory for your application (for example, app/src/main/res/raw) in your Android project. Otherwise, you will not be able to compile your application.

import android.util.Log;
import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin;
import com.amplifyframework.core.Amplify;
import com.amplifyframework.core.configuration.AmplifyOutputs;
import com.amplifyframework.storage.s3.AWSS3StoragePlugin;
Amplify.addPlugin(new AWSCognitoAuthPlugin());
Amplify.addPlugin(new AWSS3StoragePlugin());

Your class will look like this:

public class MyAmplifyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
try {
// Add these lines to add the AWSCognitoAuthPlugin and AWSS3StoragePlugin plugins
Amplify.addPlugin(new AWSCognitoAuthPlugin());
Amplify.addPlugin(new AWSS3StoragePlugin());
Amplify.configure(AmplifyOutputs.fromResource(R.raw.amplify_outputs), getApplicationContext());
Log.i("MyAmplifyApp", "Initialized Amplify");
} catch (AmplifyException error) {
Log.e("MyAmplifyApp", "Could not initialize Amplify", error);
}
}
}
import android.util.Log
import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin
import com.amplifyframework.core.Amplify
import com.amplifyframework.core.configuration.AmplifyOutputs
import com.amplifyframework.storage.s3.AWSS3StoragePlugin
Amplify.addPlugin(AWSCognitoAuthPlugin())
Amplify.addPlugin(AWSS3StoragePlugin())

Your class will look like this:

class MyAmplifyApp : Application() {
override fun onCreate() {
super.onCreate()
try {
// Add these lines to add the AWSCognitoAuthPlugin and AWSS3StoragePlugin plugins
Amplify.addPlugin(AWSCognitoAuthPlugin())
Amplify.addPlugin(AWSS3StoragePlugin())
Amplify.configure(AmplifyOutputs(R.raw.amplify_outputs), applicationContext)
Log.i("MyAmplifyApp", "Initialized Amplify")
} catch (error: AmplifyException) {
Log.e("MyAmplifyApp", "Could not initialize Amplify", error)
}
}
}
import android.util.Log;
import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin;
import com.amplifyframework.core.configuration.AmplifyOutputs;
import com.amplifyframework.rx.RxAmplify;
import com.amplifyframework.storage.s3.AWSS3StoragePlugin;
RxAmplify.addPlugin(new AWSCognitoAuthPlugin());
RxAmplify.addPlugin(new AWSS3StoragePlugin());

Your class will look like this:

public class MyAmplifyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
try {
// Add these lines to add the AWSCognitoAuthPlugin and AWSS3StoragePlugin plugins
RxAmplify.addPlugin(new AWSCognitoAuthPlugin());
RxAmplify.addPlugin(new AWSS3StoragePlugin());
RxAmplify.configure(AmplifyOutputs.fromResource(R.raw.amplify_outputs), getApplicationContext());
Log.i("MyAmplifyApp", "Initialized Amplify");
} catch (AmplifyException error) {
Log.e("MyAmplifyApp", "Could not initialize Amplify", error);
}
}
}

Note that because the storage category requires auth, you will need to either configure guest access or sign in a user before using features in the storage category.

Upload your first file

Next, let's a photo to the picture-submissions/ path.

private void uploadFile() {
File exampleFile = new File(getApplicationContext().getFilesDir(), "myPhoto.png");
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(exampleFile));
writer.append("Example file contents");
writer.close();
} catch (Exception exception) {
Log.e("MyAmplifyApp", "Upload failed", exception);
}
Amplify.Storage.uploadFile(
StoragePath.fromString("picture-submissions/myPhoto.png"),
exampleFile,
result -> Log.i("MyAmplifyApp", "Successfully uploaded: " + result.getPath()),
storageFailure -> Log.e("MyAmplifyApp", "Upload failed", storageFailure)
);
}
private fun uploadFile() {
val exampleFile = File(applicationContext.filesDir, "myPhoto.png")
exampleFile.writeText("Example file contents")
Amplify.Storage.uploadFile(StoragePath.fromString("picture-submissions/myPhoto.png"), exampleFile,
{ Log.i("MyAmplifyApp", "Successfully uploaded: ${it.path}") },
{ Log.e("MyAmplifyApp", "Upload failed", it) }
)
}
private suspend fun uploadFile() {
val exampleFile = File(applicationContext.filesDir, "myPhoto.png")
exampleFile.writeText("Example file contents")
val upload = Amplify.Storage.uploadFile(StoragePath.fromString("picture-submissions/myPhoto.png"), exampleFile)
try {
val result = upload.result()
Log.i("MyAmplifyApp", "Successfully uploaded: ${result.path}")
} catch (error: StorageException) {
Log.e("MyAmplifyApp", "Upload failed", error)
}
}
private void uploadFile() {
File exampleFile = new File(getApplicationContext().getFilesDir(), "myPhoto.png");
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(exampleFile));
writer.append("Example file contents");
writer.close();
} catch (Exception exception) {
Log.e("MyAmplifyApp", "Upload failed", exception);
}
RxProgressAwareSingleOperation<StorageUploadFileResult> rxUploadOperation =
RxAmplify.Storage.uploadFile(StoragePath.fromString("picture-submissions/myPhoto.png"), exampleFile);
rxUploadOperation
.observeResult()
.subscribe(
result -> Log.i("MyAmplifyApp", "Successfully uploaded: " + result.getPath()),
error -> Log.e("MyAmplifyApp", "Upload failed", error)
);
}

Manage files in Amplify console

After successfully publishing your storage backend and connecting your project with client APIs, you can manage files and folders in the Amplify console. You can perform on-demand actions like upload, download, copy, and more under the Storage tab in the console. Refer to Manage files in Amplify Console guide for additional information.

Conclusion

Congratulations! You finished the Set up Amplify Storage guide. In this guide, you set up and connected to backend resources, customized your file paths and access definitions, and connected your application to the backend to implement features like file uploads and downloads.

Next steps

Now that you have completed setting up storage in your Amplify app, you can proceed to add file management features to your app. You can use the following guides to implement upload and download functionality, or you can access more capabilities from the side navigation.