Migrate from v5 to v6
This guide will help you migrate Amplify JavaScript v5's Storage APIs to the new v6's Storage APIs.
Deprecated Options
The input options below have been removed in v6 from Storage APIs:
provider
: Custom providers are no longer supported in v6. All v5 examples below use the input/output values expected for the default S3 Provider.customPrefix
: You can add a prefix resolver to your Storage Config to customize the key prefix per accessLevel. See Using a Custom Prefix for migration details.track
: Auto-tracking Storage events in pinpoint has been removed in V6. You can track Storage events using the Analytics category. See Tracking storage events for migration details.ServerSideEncryption
,SSECustomerAlgorithm
,SSECustomerKey
,SSECustomerKeyMD5
, andSSEKMSKeyId
: These options have been deprecated because Server-Side Encryption is automatically applied using default keys by S3 since Jan 2023.cacheControl
: This option has been removed and now defers to the HTTP caching behavior configured by the runtime.
bucket
: Thebucket
is required forStorage
configuration object as part ofAmplify.configure()
and has therefore been removed from input options.
Note: We have remapped all capitalized input and output keys to "camelCase" in v6.
Storage.put
The Storage.put
API has been renamed to uploadData
in v6. There are a few changes in the experience from v5 to v6 in addition to those mentioned above:
- We removed the
ACL
option: the S3 Bucket ACL provides extra access control options that Amplify does not currently support. ACL is no longer recommended according to S3 security best practices. - The
Expires
option has been deprecated. - The
resumable
option has been removed fromconfig
as all upload tasks are resumable by default in v6. You can find thepause
,resume
, andcancel
functions onuploadData
's return value. See the v6 Storage documentation for details. - The
progressCallback
option on upload and download operations has been replaced byonProgress
in v6. The function input property namesloaded
andtotal
now map totransferredBytes
andtotalBytes
.
Input
V5
1// AWSS3 (Default) Provider2key: string3object: {4 ACL?: string; // removed in V65 CacheControl?: string; // removed in V66 ContentDisposition? string;7 ContentEncoding?: string;8 ContentMD5?: string;9 ContentType?: string;10 Expires?: Date; // removed in V611 Metadata?: Record<string, string>;12 ServerSideEncryption?: string; // removed in V613 SSECustomerAlgorithm?: string; // removed in V614 SSECustomerKey?: string; // removed in V615 SSECustomerKeyMD5?: string; // removed in V616 SSEKMSKeyId?: string; // removed in V617 Bucket: string;18 Key: string;19 Body?: string | ReadableStream<any> | Blob | Uint8Array | Buffer;20 Tagging?: string; // removed in V621}22// non-resumable config23config?: {24 level?: 'public' | 'protected' | 'private';25 provider?: string; // removed in V626 customPrefix?: { // removed in V627 private?: string;28 public?: string;29 protected?: string;30 };31 track?: boolean; // removed in V632 progressCallback?: (progress: any) => any;33 serverSideEncryption?: string; // removed in V634 SSECustomerAlgorithm?: string; // removed in V635 SSECustomerKey?: string; // removed in V636 SSECustomerKeyMD5?: string; // removed in V637 SSEKMSKeyId?: string; // removed in V638 acl?: string; // removed in V639 bucket?: string;40 cacheControl?: string; // removed in V641 contentDisposition?: string;42 contentEncoding?: string;43 contentType?: string;44 expires?: Date;45 metadata?: Record<string, string>;46 tagging?: string; // removed in V647 useAccelerateEndpoint?: boolean;48 resumable?: boolean; // Not required in v6: all put operations are resumable49}50// resumable config51config?: {52 // All of the standard config above plus53 progressCallback?: (progress: {54 loaded: number;55 total: number;56 }) => any; // More specific than progressCallback above57 completeCallback?: (event: { key?: string }) => any;58 errorCallback?: (err: any) => any;59}
V6
1input: {2 key: string;3 data: string | Blob | ArrayBufferView | ArrayBuffer;4 options?: {5 accessLevel?: any;6 useAccelerateEndpoint?: boolean;7 onProgress?: (event: {8 transferredBytes: number;9 totalBytes?: number;10 }) => void;11 contentDisposition?: string;12 contentEncoding?: string;13 contentType?: string;14 metadata?: Record<string, string>;15 };16}
Output
V5
1// Resumable2StoragePutOutput {3 resume(): any;4 pause(): any;5 percent: number;6 isInProgress: boolean;7}8
9// Non-resumable10StoragePutOutput {11 key: string;12};
V6
1UploadDataOutput {2 cancel: (message?: string) => void;3 pause: () => void;4 resume: () => void;5 readonly state: 6 | 'IN_PROGRESS'7 | 'PAUSED'8 | 'CANCELED'9 | 'SUCCESS'10 | 'ERROR';11 result: Promise<Item>;12}13
14Item {15 key: string;16 lastModified?: Date;17 size?: number;18 eTag?: string;19 metadata?: Record<string, string>;20 versionId?: string;21 contentType?: string;22}
1import { uploadData } from 'aws-amplify/storage';2
3const handleUpload = async (key: string, data: string | Blob) => {4 // Upload a file with access level `guest` as the equivalent of `public` in v55 const operation = uploadData({6 key,7 data,8 options: {9 accessLevel: 'guest'10 }11 });12
13 const result = await operation.result;14}
1import { Storage } from 'aws-amplify';2
3const handleUpload = async (key: string, data: string | Blob) => {4 // Upload a file with access level `public`5 const result = await Storage.put(key, data, {6 level: 'public',7 });8}
Monitor Upload Progress
The progressCallback
option has been replaced by onProgress
in v6. The function input property names loaded
and total
now map to transferredBytes
and totalBytes
.
1import { uploadData } from 'aws-amplify/storage';2
3const handleUpload = async (key: string, data: string | Blob) => {4 // Upload a file with access level `guest` as the equivalent of `public` in v55 const operation = uploadData({6 key,7 data,8 options: {9 accessLevel: 'guest',10 onProgress: ({ transferredBytes, totalBytes }) => {11 // Progress implementation12 }13 }14 });15
16 const result = await operation.result;17}
1import { Storage } from 'aws-amplify';2
3const handleUpload = async (key: string, data: string | Blob) => {4 // Upload a file with access level `public`5 const result = await Storage.put(key, data, {6 level: 'public',7 progressCallback: ({ loaded, total }) => {8 // Progress implementation9 }10 });11}
Storage.get
The Storage.get
API has been separated into two APIs in v6, getURL
and downloadData
. There are a few changes in the experience from v5 to v6 in addition to those mentioned above:
- Content options (
contentDisposition
,contentLanguage
,contentEncoding
, andcontentType
) are no longer supported in theget
API as these values are already provided in the uploaded file. - The following response keys inherited from AWS SDK in v5 have have been removed from the API output in v6:
- DeleteMarker
- AcceptRanges
- Expiration
- Restore
- ChecksumXXX
- MissingMeta
- VersionId
- ContentRange
- Expires
- WebsiteRedirectLocation
- BucketKeyEnabled
- StorageClass
- RequestCharged
- ReplicationStatus
- PartsCount
- TagCount
- ObjectLockMode
- ObjectLockRetainUntilDate
- ObjectLockLegalHoldStatus
- The
progressCallback
option on upload and download operations has been replaced byonProgress
in v6. The function input property namesloaded
andtotal
now map totransferredBytes
andtotalBytes
.
Input
V5
1// Assumes default S3 Provider2key: string3options: {4 level?: 'public' | 'protected' | 'private';5 provider?: 'AWSS3';6 customPrefix?: { // removed in V67 private?: string;8 public?: string;9 protected?: string;10 };11 track?: boolean; // removed in V612 download?: boolean; // removed in V613 expires?: number;14 identityId?: string;15 progressCallback?: (progress: any) => any;16 cacheControl?: string; // removed in V617 contentDisposition?: string; // removed in V618 contentEncoding?: string; // removed in V619 contentLanguage?: string; // removed in V620 contentType?: string; // removed in V621 SSECustomerAlgorithm?: string; // removed in V622 SSECustomerKey?: string; // removed in V623 SSECustomerKeyMD5?: string; // removed in V624 validateObjectExistence?: boolean;25};
V6
1// getUrl2{3 key: string;4 options?: {5 accessLevel?: 'guest' | 'protected' | 'private';6 // targetIdentityId?: string; // included if accessLevel is 'protected'7 useAccelerateEndpoint?: boolean;8 };9}10
11// downloadData12input: {13 key: string;14 options?: {15 accessLevel?: 'guest' | 'protected' | 'private';16 // targetIdentityId?: string; // included if accessLevel is 'protected'17 useAccelerateEndpoint?: boolean;18 onProgress?: (event: {19 transferredBytes: number;20 totalBytes?: number;21 }) => void;22 bytesRange?: {23 start: number;24 end: number;25 };26 };27}
Output
V5
1// download: false2string // presigned url3
4// download: true5S3ProviderGetOutput {6 Body?: Blob;7 DeleteMarker?: boolean; // removed in V68 AcceptRanges?: string; // removed in V69 Expiration?: string; // removed in V610 Restore?: string; // removed in V611 LastModified?: Date;12 ContentLength?: number;13 ETag?: string;14 ChecksumCRC32?: string; // removed in V615 ChecksumCRC32C?: string; // removed in V616 ChecksumSHA1?: string; // removed in V617 ChecksumSHA256?: string; // removed in V618 MissingMeta?: number; // removed in V619 VersionId?: string; // removed in V620 CacheControl?: string; // removed in V621 ContentDisposition?: string; // removed in V622 ContentEncoding?: string; // removed in V623 ContentLanguage?: string; // removed in V624 ContentRange?: string; // removed in V625 ContentType?: string;26 Expires?: Date; // removed in V627 WebsiteRedirectLocation?: string; // removed in V628 ServerSideEncryption?: ServerSideEncryption | string; // removed in V629 Metadata?: Record<string, string>;30 SSECustomerAlgorithm?: string; // removed in V631 SSECustomerKeyMD5?: string; // removed in V632 SSEKMSKeyId?: string; // removed in V633 BucketKeyEnabled?: boolean; // removed in V634 StorageClass?: StorageClass | string; // removed in V635 RequestCharged?: RequestCharged | string; // removed in V636 ReplicationStatus?: ReplicationStatus | string; // removed in V637 PartsCount?: number; // removed in V638 TagCount?: number; // removed in V639 ObjectLockMode?: ObjectLockMode | string; // removed in V640 ObjectLockRetainUntilDate?: Date; // removed in V641 ObjectLockLegalHoldStatus?: ObjectLockLegalHoldStatus | string; // removed in V642 $metadata: { // removed in V643 httpStatusCode?: number;44 requestId?: string45 }46}
V6
1// getUrl2GetUrlOutput {3 url: URL;4 expiresAt: Date;5}6
7// downloadData8DownloadDataOutput {9 cancel: (message?: string) => void;10 readonly state: TransferTaskState;11 result: Promise<StorageDownloadDataOutput<Item>>;12}13
14StorageDownloadDataOutput<Item> {15 key: string;16 lastModified?: Date;17 size?: number;18 eTag?: string;19 metadata?: Record<string, string>;20 versionId?: string;21 contentType?: string;22 body: {23 blob: () => Promise<Blob>;24 json: () => Promise<any>;25 text: () => Promise<string>;26 };27}
Get URL Only (Default)
1import { getUrl } from 'aws-amplify/storage';2
3const handleGetUrl = async (key: string) => {4 const url = await getUrl({5 key,6 options: {7 validateObjectExistence: true8 },9 });10}
1import { Storage } from 'aws-amplify';2
3const handleGetUrl = async (key: string) => {4 const url = await Storage.get(key, {5 validateObjectExistence: true6 });7}
Download File Content to Memory
1import { downloadData } from 'aws-amplify/storage';2
3const handleDownload = async (key: string) => {4 const { body, eTag } = await downloadData({ key }).result;5}
1import { Storage } from 'aws-amplify';2
3const handleDownload = async (key: string) => {4 const { Body, ETag } = await Storage.get(key, {5 download: true6 });7}
Monitor Download Progress
The progressCallback
option has been replaced by onProgress
in v6. The function input property names loaded
and total
now map to transferredBytes
and totalBytes
.
1import { downloadData } from 'aws-amplify/storage';2
3const handleDownload = async (key: string) => {4 const { body, eTag } = await downloadData({5 key,6 options: {7 onProgress: ({ transferredBytes, totalBytes }) => {8 // Progress implementation9 }10 }11 }).result;12}
1import { Storage } from 'aws-amplify';2
3const handleDownload = async (key: string) => {4 const { Body, ETag } = await Storage.get(key, {5 download: true,6 progressCallback: ({ loaded, total }) => {7 // Progress implementation8 }9 });10}
Storage.copy
In addition to the changes mentioned above, the copy
API in v6 no longer supports content options (contentDisposition
, contentLanguage
, and contentType
) as these values are already provided by the existing file.
Input
V5
1// Assumes default S3 Provider2src: {3 key: string;4 level?: string;5 identityId?: string;6}7dest: {8 level?: string;9 key: string;10}11config?: {12 provider?: 'AWSS3';13 customPrefix?: { // removed in V614 public?: string;15 protected?: string;16 private?: string;17 };18 track?: boolean; // removed in V619 bucket?: string;20 cacheControl?: string; // removed in V621 contentDisposition?: string; // removed in V622 contentLanguage?: string; // removed in V623 contentType?: string; // removed in V624 expires?: Date;25 tagging?: string; // removed in V626 acl?: 27 | 'private' 28 | 'authenticated-read' 29 | 'aws-exec-read' 30 | 'bucket-owner-full-control' 31 | 'bucket-owner-read' 32 | 'public-read' 33 | 'public-read-write'34 | string;35 metadata?: Record<string, string>;36 serverSideEncryption?: 'AES256' | 'aws:kms';37 SSECustomerAlgorithm?: string; // removed in V638 SSECustomerKey?: string; // removed in V639 SSECustomerKeyMD5?: string; // removed in V640 SSEKMSKeyId?: string; // removed in V641}
V6
1input: {2 source: {3 key: string;4 accessLevel?: 'guest' | 'protected' | 'private';5 // Included when accessLevel 'protected'6 targetIdentityId?: string;7 };8 destination: {9 key: string;10 accessLevel?: any;11 };12}
Output
V5
1S3ProviderCopyOutput {2 key: string;3}
V6
1CopyOutput {2 key: string;3}
1import { copy } from 'aws-amplify/storage';2
3const handleCopy = async (sourceKey: string, destinationKey: string) => {4 const { key } = await copy({5 source: {6 key: sourceKey7 },8 destination: {9 key: destinationKey10 },11 });12};
1import { Storage } from 'aws-amplify';2
3const handleCopy = async (sourceKey: string, destinationKey: string) => {4 const { key } = await Storage.copy(5 src: {6 key: sourceKey7 },8 dest: { 9 key: destinationKey10 }11 )12};
Storage.remove
In addition to the changes mentioned above, the output of the remove
API in v6 now only returns the key
of the removed file. DeleteMarker
, VersionId
, RequestCharged
, and $metadata
have been removed from the output.
Input
V5
1// Assumes default S3 Provider2key: string3 config?: {4 level?: 'public' | 'protected' | 'private';5 provider?: 'AWSS3';6 customPrefix?: { // removed in V67 public?: string;8 protected?: string;9 private?: string;10 };11 track?: boolean; // removed in V612 bucket?: string;13}
V6
1input: {2 key: string;3 options?: {4 accessLevel?: any;5 useAccelerateEndpoint?: boolean;6 };7}
Output
V5
1DeleteMarker?: boolean; // removed in V62VersionId?: string; // removed in V63RequestCharged?: 'requester' | string; // removed in V64$metadata: { // removed in V65 httpStatusCode?: number;6 requestId?: string;7 extendedRequestId?: string;8 cfId?: string;9 attempts?: number;10 totalRetryDelay?: number;11};
V6
1RemoveOutput {2 key: string;3}
1import { remove } from 'aws-amplify/storage';2
3const handleRemove = async (key: string, accessLevel: string) => {4 await remove({ 5 key,6 options: {7 // accessLevel is required if other than 'guest'8 accessLevel9 }10 });11}
1import { Storage } from 'aws-amplify';2
3const handleRemove = async (key: string, accessLevel: string) => {4 await Storage.remove(key, {5 // accessLevel is required if other than 'public'6 level: accessLevel7 });8}
Storage.list
There are a few changes in the list
API from v5 to v6 in addition to those mentioned above:
- The
path
parameter is now the optionalprefix
parameter. If you want to list all files in the public folder, you do not need to provide an empty string as theprefix
. - The
hasNextToken
output property has been removed. You can check thatnextToken
is defined to check if there are more items to retrieve.
Input
V5
1// Assumes default S3 Provider2path: string,3config?: {4 level?: 'public' | 'protected' | 'private';5 provider?: 'AWSS3';6 customPrefix?: { // removed in V67 private?: string;8 public?: string;9 protected?: string;10 };11 track?: boolean; // removed in V612 bucket?: string;13 pageSize?: number | 'ALL';14 identityId?: string;15 nextToken?: string;16}
V6
1// Paginated List2input {3 prefix?: string;4 options?: {5 listAll?: false;6 accessLevel?: 'guest' | 'protected' | 'private';7 pageSize?: number;8 nextToken?: string;9 useAccelerateEndpoint?: boolean;10 // Included if accessLevel is 'protected'11 targetIdentityId?: string';12 };13}14
15// List All16input {17 prefix?: string;18 options?: {19 listAll: true;20 accessLevel?: 'guest' | 'protected' | 'private';21 useAccelerateEndpoint?: boolean;22 // Included if accessLevel is 'protected'23 targetIdentityId?: string';24 };25}
Output
V5
1StorageListOutput {2 results: S3ProviderListOutputItem[];3 nextToken?: string;4 hasNextToken: boolean; // removed in V65};6
7S3ProviderListOutputItem {8 key: string;9 eTag: string;10 lastModified: Date;11 size: number;12}
V6
1// Paginated List2ListPaginateOutput {3 items: ListOutputItem[];4 nextToken?: string;5}6
7// List All8ListAllOutput {9 items: ListOutputItem[];10}11
12ListOutputItem {13 key: string;14 lastModified?: Date;15 size?: number;16 eTag?: string;17}
Paginated List (Default)
1import { list } from 'aws-amplify/storage';2
3const PAGE_SIZE = 20;4let nextToken = undefined;5let hasNextPage = true;6
7const loadNextPage = async () => {8 if (hasNextPage) {9 let response = await list({10 options: {11 pageSize: PAGE_SIZE,12 nextToken: nextToken13 }14 });15 if (response.nextToken) {16 nextToken = response.nextToken;17 } else {18 nextToken = undefined;19 hasNextPage = false;20 }21 // render list items from response.results22 }23};
1import { Storage } from 'aws-amplify';2
3const PAGE_SIZE = 20;4let nextToken = undefined;5let hasNextPage = true;6
7const loadNextPage = async () => {8 if (hasNextPage) {9 let response = await Storage.list('', {10 pageSize: PAGE_SIZE,11 nextToken: nextToken12 });13 if (response.hasNextToken) {14 nextToken = response.nextToken;15 } else {16 nextToken = undefined;17 hasNextPage = false;18 }19 // render list items from response.results20 }21};
All Files
1import { list } from 'aws-amplify/storage';2
3const handleListAll = async (4 prefix: string, 5 accessLevel: string,6 id: string7) => {8 const { items } = list({9 prefix,10 options: {11 listAll: true,12 // accessLevel and targetIdentityId not required if accessLevel is 'guest'13 accessLevel,14 targetIdentityId: id,15 }16 });17}
1import { Storage } from 'aws-amplify';2
3const handleListAll = async (4 prefix: string, 5 accessLevel: string,6 id: string7) => {8 const { results } = Storage.list(prefix, {9 pageSize: 'ALL',10 // level and identityId not required if level is 'public'11 level: accessLevel,12 identityId: id13 });14}
Storage.getProperties
In addition to the changes mentioned above, the getProperties
API in v6 also adds key
to the result.
Input
V5
1key: string2 config?: {3 level?: 'public' | 'protected' | 'private';4 provider?: string; // removed in V65 customPrefix?: { // removed in V66 private?: string;7 public?: string;8 protected?: string;9 };10 track?: boolean; // removed in V611 SSECustomerAlgorithm?: string; // removed in V612 SSECustomerKey?: string; // removed in V613 SSECustomerKeyMD5?: string; // removed in V614}
V6
1input: {2 key: string;3 options?: {4 accessLevel?: 'guest' | 'protected' | 'private';5 useAccelerateEndpoint?: boolean;6 // Included if accessLevel is 'protected'7 targetIdentityId?: string;8 };9}
Output
V5
1StorageGetPropertiesOutput {2 contentType: string;3 contentLength: number;4 eTag: string;5 lastModified: Date;6 metadata: Record<string, string>;7};
V6
1GetPropertiesOutput {2 key: string;3 lastModified?: Date;4 size?: number';5 eTag?: string';6 metadata?: Record<string, string>';7 versionId?: string;8 contentType?: string;9}
1import { getProperties } from 'aws-amplify/storage';2
3const handleGetProperties = async (4 key: string,5 accessLevel: string6) => {7 const result = await getProperties({8 key: 'key',9 options: {10 // accessLevel not required if accessLevel is 'guest'11 accessLevel,12 }13 });14}
1import { Storage } from 'aws-amplify';2
3const handleGetProperties = async (4 key: string,5 accessLevel: string6) => {7 const result = await Storage.getProperties(key, {8 // level not required if level is 'public'9 level: accessLevel,10 });11}
Storage.cancel
The process for cancelling a request has changed in v6. In v5, you have to maintain the promise or UploadTask reference returned from a Storage API call, and supply it as input to the Storage.cancel
API. In v6, cancel
is a function returned with the result of a Storage operation. To cancel an operation, you will call operation.cancel()
.
1import { downloadData } from 'aws-amplify/storage';2
3const operation = downloadData({4 apiName,5 path,6 options7});8
9operation.response.then(result => {10 // GET operation completed successfully11}).catch(error => {12 // If the error is because the request was cancelled you can confirm here.13 if(isCancelError(error)) {14 // 'my message for cancellation'15 console.log(error.message);16 }17})18
19// To cancel the above request20operation.cancel('my message for cancellation');
1import { Storage } from 'aws-amplify';2
3const operation = Storage.get(key, options);4
5operation.then(result => {6 // GET operation completed successfully7}).catch(error => {8 // If the error is because the request was cancelled you can confirm here.9 if(Storage.isCancel(error)) {10 // 'my message for cancellation'11 console.log(error.message);12 }13});14
15// To cancel the above request16Storage.cancel(operation, 'my message for cancellation');
Using a Custom Prefix
If you would like to upload or download items with a customPrefix
, you can configure a prefix resolver in the second parameter of Amplify.configure
, libraryOptions
. Keep in mind that you will need to resolve each accessLevel
in the custom prefixResolver
. The example below shows the default for protected
and private
access levels and a customPrefix for guest
.
1import { uploadData } from 'aws-amplify/storage';2import { Amplify } from 'aws-amplify';3import amplifyconfig from './amplifyconfiguration.json';4
5const libraryOptions = {6 Storage: {7 S3: {8 prefixResolver: async ({ accessLevel, targetIdentityId }) => {9 if (accessLevel === 'guest') {10 return 'publicPrefix/';11 } else if (accessLevel === 'protected') {12 return `protected/${targetIdentityId}/`;13 } else {14 return `private/${targetIdentityId}/`;15 }16 }17 }18 }19};20
21Amplify.configure(amplifyConfig, libraryOptions);22
23const handleUpload = async (key: string, data: string | Blob) => {24 // Upload a file with access level `guest` as the equivalent of `public` in v525 const operation = uploadData({26 key,27 data,28 options: {29 accessLevel: 'guest'30 }31 });32
33 const result = await operation.result;34}
1import { Storage } from 'aws-amplify';2
3const handleUpload = async (key: string, data: string | Blob) => {4 // Upload a file with access level `public`5 const result = await Storage.put(key, data, {6 level: 'public',7 customPrefix: {8 public: 'publicPrefix'9 }10 });11}
Tracking storage events
The track
option has been removed from Storage and its APIs in v6. Previously, in v5, enabling this option would automatically send analytics events to Pinpoint following the success or failure of Storage API calls. The analytic events sent were defined by Amplify and therefore not configurable. In v6, this option has been removed but you can continue to track Storage API results in a more predictable and configurable way using the Analytics category.
The table below lists the analytics events previously associated to v5 APIs and the corresponding v6 APIs they should now be associated with instead.
Analytics event | V5 API | V6 API |
---|---|---|
'copy' | copy | copy |
'download' | get (download: true ) | downloadData |
'getSignedUrl' | get | getUrl |
'getProperties' | getProperties | getProperties |
'upload' | put | uploadData |
'delete' | remove | remove |
'list' | list | list |
1import { list } from 'aws-amplify/storage';2import { record } from 'aws-amplify/analytics';3
4const prefix = 'photos/';5
6try {7 const result = await list({ prefix });8 record({9 name: 'list',10 attributes: { result: 'success' },11 });12 // Do something with the result13} catch (error) {14 record({15 name: 'list',16 attributes: { result: 'failure' },17 });18 // Do something with the error19};
1import { Storage } from 'aws-amplify';2
3const prefix = 'photos/';4
5Storage.configure({ track: true });6
7try {8 const result = Storage.list(prefix);9 // Do something with the result10} catch (error) {11 // Do something with the error12}