Page updated Nov 16, 2023

List files

Guest level list

import { list } from 'aws-amplify/storage'; try { const result = await list({ prefix: 'photos/' }); } catch (error) { console.log(error); }
1import { list } from 'aws-amplify/storage';
2
3try {
4 const result = await list({
5 prefix: 'photos/'
6 });
7} catch (error) {
8 console.log(error);
9}

Note the trailing slash / - if you had requested list({ prefix : 'photos' }) it would also match against files like photos123.jpg alongside photos/123.jpg.

The format of the response will look similar to the below example

{ items: [ { key: "filename", eTag: "30074401292215403a42b0739f3b5262", lastModified: "Thu Oct 08 2020 23:59:31 GMT+0800 (Singapore Standard Time)", size: 138256 }, // ... ], }
1{
2 items: [
3 {
4 key: "filename",
5 eTag: "30074401292215403a42b0739f3b5262",
6 lastModified: "Thu Oct 08 2020 23:59:31 GMT+0800 (Singapore Standard Time)",
7 size: 138256
8 },
9 // ...
10 ],
11}

Manually created folders will show up as files with a size of 0, but you can also match keys against a regex like file.key.match(/\.[0-9a-z]+$/i) to distinguish files from folders. Since "folders" are a virtual concept in S3, any file may declare any depth of folder just by having a / in its name. If you need to list all the folders, you'll have to parse them accordingly to get an authoritative list of files and folders:

function processStorageList(response) { let files = []; let folders = new Set(); response.items.forEach((res) => { if (res.size) { files.push(res); // sometimes files declare a folder with a / within then let possibleFolder = res.key.split('/').slice(0, -1).join('/'); if (possibleFolder) folders.add(possibleFolder); } else { folders.add(res.key); } }); return { files, folders }; }
1function processStorageList(response) {
2 let files = [];
3 let folders = new Set();
4 response.items.forEach((res) => {
5 if (res.size) {
6 files.push(res);
7 // sometimes files declare a folder with a / within then
8 let possibleFolder = res.key.split('/').slice(0, -1).join('/');
9 if (possibleFolder) folders.add(possibleFolder);
10 } else {
11 folders.add(res.key);
12 }
13 });
14 return { files, folders };
15}

If you need the files and folders in terms of a nested object instead (for example, to build an explorer UI), you could parse it recursively:

function processStorageList(response) { const filesystem = {}; // https://stackoverflow.com/questions/44759750/how-can-i-create-a-nested-object-representation-of-a-folder-structure const add = (source, target, item) => { const elements = source.split('/'); const element = elements.shift(); if (!element) return; // blank target[element] = target[element] || { __data: item }; // element; if (elements.length) { target[element] = typeof target[element] === 'object' ? target[element] : {}; add(elements.join('/'), target[element], item); } }; response.items.forEach((item) => add(item.key, filesystem, item)); return filesystem; }
1function processStorageList(response) {
2 const filesystem = {};
3 // https://stackoverflow.com/questions/44759750/how-can-i-create-a-nested-object-representation-of-a-folder-structure
4 const add = (source, target, item) => {
5 const elements = source.split('/');
6 const element = elements.shift();
7 if (!element) return; // blank
8 target[element] = target[element] || { __data: item }; // element;
9 if (elements.length) {
10 target[element] =
11 typeof target[element] === 'object' ? target[element] : {};
12 add(elements.join('/'), target[element], item);
13 }
14 };
15 response.items.forEach((item) => add(item.key, filesystem, item));
16 return filesystem;
17}

This places each item's data inside a special __data key.

Protected level list

To list current user's objects:

import { list } from 'aws-amplify/storage'; try { const response = await list({ prefix: 'photos/', options: { accessLevel: 'protected', } }); console.log('Listed Items:', response.items); } catch(error) { console.log('Error ': error); }
1import { list } from 'aws-amplify/storage';
2
3try {
4 const response = await list({
5 prefix: 'photos/',
6 options: {
7 accessLevel: 'protected',
8 }
9 });
10 console.log('Listed Items:', response.items);
11} catch(error) {
12 console.log('Error ': error);
13}

To list other user's objects:

import { list } from 'aws-amplify/storage'; try { const response = await list({ prefix: 'photos/', options: { accessLevel: 'protected', targetIdentityId: 'xxxxxxx' // the identityId of that user } }); console.log('Listed Items:', response.items); } catch(error) { console.log('Error ': error); }
1import { list } from 'aws-amplify/storage';
2
3try {
4 const response = await list({
5 prefix: 'photos/',
6 options: {
7 accessLevel: 'protected',
8 targetIdentityId: 'xxxxxxx' // the identityId of that user
9 }
10 });
11 console.log('Listed Items:', response.items);
12} catch(error) {
13 console.log('Error ': error);
14}

Private level list

import { list } from 'aws-amplify/storage'; try { const response = await list({ prefix: 'photos/', options: { accessLevel: 'private', } }); console.log('Listed Items:', response.items); } catch(error) { console.log('Error ': error); }
1import { list } from 'aws-amplify/storage';
2
3try {
4 const response = await list({
5 prefix: 'photos/',
6 options: {
7 accessLevel: 'private',
8 }
9 });
10 console.log('Listed Items:', response.items);
11} catch(error) {
12 console.log('Error ': error);
13}

Access all files

To get a list of all files in your S3 bucket under a specific prefix, you can set listAll to true.

import { list } from 'aws-amplify/storage'; try { const response = await list({ prefix: 'photos/', options: { listAll: true } }); // render list items from response.items } catch (error) { console.log('Error ', error); }
1import { list } from 'aws-amplify/storage';
2
3try {
4 const response = await list({
5 prefix: 'photos/',
6 options: {
7 listAll: true
8 }
9 });
10 // render list items from response.items
11} catch (error) {
12 console.log('Error ', error);
13}

Paginated file access

If the pageSize is set lower than the total file size, a single list call only returns a subset of all the files. To list all the files with multiple calls, users can use the nextToken flag:

import { list } from 'aws-amplify/storage'; const PAGE_SIZE = 20; let nextToken = undefined; //... const loadNextPage = async () => { let response = await list({ options: { pageSize: PAGE_SIZE, nextToken: nextToken } }); if (response.nextToken) { nextToken = response.nextToken; } else { nextToken = undefined; } // render list items from response.items };
1import { list } from 'aws-amplify/storage';
2
3const PAGE_SIZE = 20;
4let nextToken = undefined;
5//...
6const loadNextPage = async () => {
7 let response = await list({
8 options: {
9 pageSize: PAGE_SIZE,
10 nextToken: nextToken
11 }
12 });
13 if (response.nextToken) {
14 nextToken = response.nextToken;
15 } else {
16 nextToken = undefined;
17 }
18 // render list items from response.items
19};
Note: The range of pageSize can be from 0 - 1000.