Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

storage(android): update storage list with delimiter support #7830

Merged
merged 9 commits into from
Jul 30, 2024
228 changes: 220 additions & 8 deletions src/fragments/lib/storage/android/list.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
You can list all of the objects uploaded under a given prefix by setting the pageSize. If the pageSize is set lower than the total file size available,
A single `Storage.list` call only returns a subset of all the files. To list all the files with multiple calls, the user can use the nextToken from the previous call response.
You can list files without having to download all the files. You can do this by using the list API from the Amplify Library for Storage.

#### With StoragePath
This will list all public files in the path:
## With StoragePath
The following example lists all objects inside the `public/photos/` path:

<BlockSwitcher>
<Block name="Java">
Expand All @@ -13,7 +12,7 @@ StoragePagedListOptions options = StoragePagedListOptions.builder()
.build();

Amplify.Storage.list(
StoragePath.fromString("public/"),
StoragePath.fromString("public/photos/"),
options,
result -> {
for (StorageItem item : result.getItems()) {
Expand All @@ -33,7 +32,7 @@ val options = StoragePagedListOptions.builder()
.setPageSize(1000)
.build()

Amplify.Storage.list(StoragePath.fromString("public/"), options,
Amplify.Storage.list(StoragePath.fromString("public/photos/"), options,
{ result ->
result.items.forEach { item ->
Log.i("MyAmplifyApp", "Item: ${item.path}")
Expand All @@ -53,7 +52,7 @@ val options = StoragePagedListOptions.builder()
.build()

try {
val result = Amplify.Storage.list(StoragePath.fromString("public/"), options)
val result = Amplify.Storage.list(StoragePath.fromString("public/photos/"), options)
result.items.forEach {
Log.i("MyAmplifyApp", "Item: $it")
}
Expand All @@ -71,7 +70,209 @@ StoragePagedListOptions options = StoragePagedListOptions.builder()
.setPageSize(1000)
.build();

RxAmplify.Storage.list(StoragePath.fromString("public/"), options)
RxAmplify.Storage.list(StoragePath.fromString("public/photos/"), options)
.subscribe(
result -> {
for (StorageItem item : result.getItems()) {
Log.i("MyAmplifyApp", "Item: " + item.getPath());
}
Log.i("MyAmplifyApp", "Next Token: " + result.getNextToken());
},
error -> Log.e("MyAmplifyApp", "List failure", error);
);
```

</Block>
</BlockSwitcher>

<Callout>
Note the trailing slash `/` in the given path.

If you had used `public/photos` as path, it would also match against files like `public/photos01.jpg`.
</Callout>

### Exclude results from nested subpaths

By default, the `list` API will return all objects contained within the given path, including objects inside nested subpaths.

For example, the previous `public/photos/` path would include these objects:

```bash
Path: public/photos/photo1.jpg
Path: public/photos/vacation/photo1.jpg
Path: public/photos/thumbnails/photo1.jpg
```

In order to exclude objects within the `vacation` and `thumbnails` subpaths, you can set the `subpathStrategy` option to `SubpathStrategy.Exclude()`:

<BlockSwitcher>
<Block name="Java">

```java
StoragePagedListOptions options = StoragePagedListOptions.builder()
.setPageSize(1000)
.setSubpathStrategy(SubpathStrategy.Exclude())
.build();

Amplify.Storage.list(
StoragePath.fromString("public/photos/"),
options,
result -> {
for (StorageItem item : result.getItems()) {
Log.i("MyAmplifyApp", "Item: " + item.getPath());
}
Log.i("MyAmplifyApp", "Next Token: " + result.getNextToken());
},
error -> Log.e("MyAmplifyApp", "List failure", error);
);
```

</Block>
<Block name="Kotlin - Callbacks">

```kotlin
val options = StoragePagedListOptions.builder()
.setPageSize(1000)
.setSubpathStrategy(SubpathStrategy.Exclude())
.build()

Amplify.Storage.list(StoragePath.fromString("public/photos/"), options,
{ result ->
result.items.forEach { item ->
Log.i("MyAmplifyApp", "Item: ${item.path}")
}
Log.i("MyAmplifyApp", "Next Token: ${result.nextToken}")
},
{ Log.e("MyAmplifyApp", "List failure", it) }
)
```

</Block>
<Block name="Kotlin - Coroutines">

```kotlin
val options = StoragePagedListOptions.builder()
.setPageSize(1000)
.setSubpathStrategy(SubpathStrategy.Exclude())
.build()

try {
val result = Amplify.Storage.list(StoragePath.fromString("public/photos/"), options)
result.items.forEach {
Log.i("MyAmplifyApp", "Item: $it")
}
Log.i("MyAmplifyApp", "next token: ${result.nextToken}")
} catch (error: StorageException) {
Log.e("MyAmplifyApp", "List failure", error)
}
```

</Block>
<Block name="RxJava">

```java
StoragePagedListOptions options = StoragePagedListOptions.builder()
.setPageSize(1000)
.setSubpathStrategy(SubpathStrategy.Exclude())
.build();

RxAmplify.Storage.list(StoragePath.fromString("public/photos/"), options)
.subscribe(
result -> {
for (StorageItem item : result.getItems()) {
Log.i("MyAmplifyApp", "Item: " + item.getPath());
}
Log.i("MyAmplifyApp", "Next Token: " + result.getNextToken());
},
error -> Log.e("MyAmplifyApp", "List failure", error);
);
```

</Block>
</BlockSwitcher>

The response will only include objects within the `public/photos/` path and will also provide a list of the excluded subpaths:

```bash
Path: public/photos/photo01.jpg
Subpath: public/photos/vacation/
Subpath: public/photos/thumbnails/
```

The default delimiter character is `"/"`, but this can be changed by supplying a custom delimiter:
lawmicha marked this conversation as resolved.
Show resolved Hide resolved

<BlockSwitcher>
<Block name="Java">

```java
StoragePagedListOptions options = StoragePagedListOptions.builder()
.setPageSize(1000)
.setSubpathStrategy(SubpathStrategy.Exclude("-"))
.build();

Amplify.Storage.list(
StoragePath.fromString("public/photos-"),
options,
result -> {
for (StorageItem item : result.getItems()) {
Log.i("MyAmplifyApp", "Item: " + item.getPath());
}
Log.i("MyAmplifyApp", "Next Token: " + result.getNextToken());
},
error -> Log.e("MyAmplifyApp", "List failure", error);
);
```

</Block>
<Block name="Kotlin - Callbacks">

```kotlin
val options = StoragePagedListOptions.builder()
.setPageSize(1000)
.setSubpathStrategy(SubpathStrategy.Exclude("-"))
.build()

Amplify.Storage.list(StoragePath.fromString("public/photos-"), options,
{ result ->
result.items.forEach { item ->
Log.i("MyAmplifyApp", "Item: ${item.path}")
}
Log.i("MyAmplifyApp", "Next Token: ${result.nextToken}")
},
{ Log.e("MyAmplifyApp", "List failure", it) }
)
```

</Block>
<Block name="Kotlin - Coroutines">

```kotlin
val options = StoragePagedListOptions.builder()
.setPageSize(1000)
.setSubpathStrategy(SubpathStrategy.Exclude("-"))
.build()

try {
val result = Amplify.Storage.list(StoragePath.fromString("public/photos-"), options)
result.items.forEach {
Log.i("MyAmplifyApp", "Item: $it")
}
Log.i("MyAmplifyApp", "next token: ${result.nextToken}")
} catch (error: StorageException) {
Log.e("MyAmplifyApp", "List failure", error)
}
```

</Block>
<Block name="RxJava">

```java
StoragePagedListOptions options = StoragePagedListOptions.builder()
.setPageSize(1000)
.setSubpathStrategy(SubpathStrategy.Exclude("-"))
.build();

RxAmplify.Storage.list(StoragePath.fromString("public/photos-"), options)
.subscribe(
result -> {
for (StorageItem item : result.getItems()) {
Expand Down Expand Up @@ -264,3 +465,14 @@ RxAmplify.Storage.list("", options)

</Block>
</BlockSwitcher>

### More `list` options

| Option | Type | Description |
| --- | --- | --- |
| pageSize | int | Number between 1 and 1,000 that indicates the limit of how many entries to fetch when retrieving file lists from the server |
| nextToken | String | String indicating the page offset at which to resume a listing. |


If the `pageSize` is set lower than the total file size available, a single `list` call only returns a subset of all the files. To list all the files with multiple calls, the user can use the `nextToken` value from the previous response.

Loading