list.ts

_39
import type { APIRoute } from "astro";
_39
_39
export const GET: APIRoute = async ({ request, locals }) => {
_39
try {
_39
// Check if bucket is available
_39
const bucket = locals.runtime.env.CLOUD_FILES;
_39
if (!bucket) {
_39
return new Response("Cloud storage not configured", { status: 500 });
_39
}
_39
_39
const options = { limit: 500 };
_39
const listed = await bucket.list(options);
_39
let truncated = listed.truncated;
_39
_39
// Paging through the files
_39
// @ts-ignore
_39
let cursor = truncated ? listed.cursor : undefined;
_39
_39
while (truncated) {
_39
const next = await bucket.list({
_39
...options,
_39
cursor: cursor,
_39
});
_39
listed.objects.push(...next.objects);
_39
_39
truncated = next.truncated;
_39
// @ts-ignore
_39
cursor = next.cursor;
_39
}
_39
_39
// Return the files as a JSON object
_39
return new Response(JSON.stringify(listed.objects), {
_39
headers: { "Content-Type": "application/json" },
_39
});
_39
} catch (error) {
_39
console.error("Error listing assets:", error);
_39
return new Response("Failed to list assets", { status: 500 });
_39
}
_39
};

Create the GET endpoint

Import the APIRoute type from "astro" and create a GET endpoint that accepts the locals parameter.

The locals object provides access to runtime environment variables and bindings, including the CLOUD_FILES binding that you'll use to interact with object storage.

Get the bucket and validate configuration

Access the CLOUD_FILES binding from locals.runtime.env and validate that the bucket is properly configured.

If the bucket isn't available, return a 500 error with a descriptive message to help with debugging.

list.ts

_39
import type { APIRoute } from "astro";
_39
_39
export const GET: APIRoute = async ({ request, locals }) => {
_39
try {
_39
// Check if bucket is available
_39
const bucket = locals.runtime.env.CLOUD_FILES;
_39
if (!bucket) {
_39
return new Response("Cloud storage not configured", { status: 500 });
_39
}
_39
_39
const options = { limit: 500 };
_39
const listed = await bucket.list(options);
_39
let truncated = listed.truncated;
_39
_39
// Paging through the files
_39
// @ts-ignore
_39
let cursor = truncated ? listed.cursor : undefined;
_39
_39
while (truncated) {
_39
const next = await bucket.list({
_39
...options,
_39
cursor: cursor,
_39
});
_39
listed.objects.push(...next.objects);
_39
_39
truncated = next.truncated;
_39
// @ts-ignore
_39
cursor = next.cursor;
_39
}
_39
_39
// Return the files as a JSON object
_39
return new Response(JSON.stringify(listed.objects), {
_39
headers: { "Content-Type": "application/json" },
_39
});
_39
} catch (error) {
_39
console.error("Error listing assets:", error);
_39
return new Response("Failed to list assets", { status: 500 });
_39
}
_39
};

List files with pagination support

Use the .list() method to retrieve files from the bucket.

The method returns an R2Object list with pagination support. Set a limit of 500 files per request to balance performance and memory usage. The response includes a truncated flag indicating if more files are available, and a cursor for pagination.

list.ts

_39
import type { APIRoute } from "astro";
_39
_39
export const GET: APIRoute = async ({ request, locals }) => {
_39
try {
_39
// Check if bucket is available
_39
const bucket = locals.runtime.env.CLOUD_FILES;
_39
if (!bucket) {
_39
return new Response("Cloud storage not configured", { status: 500 });
_39
}
_39
_39
const options = { limit: 500 };
_39
const listed = await bucket.list(options);
_39
let truncated = listed.truncated;
_39
_39
// Paging through the files
_39
// @ts-ignore
_39
let cursor = truncated ? listed.cursor : undefined;
_39
_39
while (truncated) {
_39
const next = await bucket.list({
_39
...options,
_39
cursor: cursor,
_39
});
_39
listed.objects.push(...next.objects);
_39
_39
truncated = next.truncated;
_39
// @ts-ignore
_39
cursor = next.cursor;
_39
}
_39
_39
// Return the files as a JSON object
_39
return new Response(JSON.stringify(listed.objects), {
_39
headers: { "Content-Type": "application/json" },
_39
});
_39
} catch (error) {
_39
console.error("Error listing assets:", error);
_39
return new Response("Failed to list assets", { status: 500 });
_39
}
_39
};

Key concepts:

  • Pagination: Buckets may contain thousands of files, so you use pagination to retrieve them in manageable chunks
  • Cursor-based pagination: Each response includes a cursor that points to the next page of results

Return the files as JSON

Return the complete list of files as a JSON response with proper headers. The listed.objects array contains all the files from the bucket, including metadata like file names, sizes, and creation dates.

list.ts

_39
import type { APIRoute } from "astro";
_39
_39
export const GET: APIRoute = async ({ request, locals }) => {
_39
try {
_39
// Check if bucket is available
_39
const bucket = locals.runtime.env.CLOUD_FILES;
_39
if (!bucket) {
_39
return new Response("Cloud storage not configured", { status: 500 });
_39
}
_39
_39
const options = { limit: 500 };
_39
const listed = await bucket.list(options);
_39
let truncated = listed.truncated;
_39
_39
// Paging through the files
_39
// @ts-ignore
_39
let cursor = truncated ? listed.cursor : undefined;
_39
_39
while (truncated) {
_39
const next = await bucket.list({
_39
...options,
_39
cursor: cursor,
_39
});
_39
listed.objects.push(...next.objects);
_39
_39
truncated = next.truncated;
_39
// @ts-ignore
_39
cursor = next.cursor;
_39
}
_39
_39
// Return the files as a JSON object
_39
return new Response(JSON.stringify(listed.objects), {
_39
headers: { "Content-Type": "application/json" },
_39
});
_39
} catch (error) {
_39
console.error("Error listing assets:", error);
_39
return new Response("Failed to list assets", { status: 500 });
_39
}
_39
};

Response format: The returned JSON will contain an array of R2Object items, each with properties like:

  • key: The file name/path
  • size: File size in bytes
  • etag: Entity tag for caching
  • httpEtag: HTTP-compatible entity tag
  • uploaded: Upload timestamp
  • checksums: File integrity checksums
  • httpMetadata: HTTP headers and metadata

Create the GET endpoint

Import the APIRoute type from "astro" and create a GET endpoint that accepts the locals parameter.

The locals object provides access to runtime environment variables and bindings, including the CLOUD_FILES binding that you'll use to interact with object storage.

Get the bucket and validate configuration

Access the CLOUD_FILES binding from locals.runtime.env and validate that the bucket is properly configured.

If the bucket isn't available, return a 500 error with a descriptive message to help with debugging.

List files with pagination support

Use the .list() method to retrieve files from the bucket.

The method returns an R2Object list with pagination support. Set a limit of 500 files per request to balance performance and memory usage. The response includes a truncated flag indicating if more files are available, and a cursor for pagination.

Key concepts:

  • Pagination: Buckets may contain thousands of files, so you use pagination to retrieve them in manageable chunks
  • Cursor-based pagination: Each response includes a cursor that points to the next page of results

Return the files as JSON

Return the complete list of files as a JSON response with proper headers. The listed.objects array contains all the files from the bucket, including metadata like file names, sizes, and creation dates.

Response format: The returned JSON will contain an array of R2Object items, each with properties like:

  • key: The file name/path
  • size: File size in bytes
  • etag: Entity tag for caching
  • httpEtag: HTTP-compatible entity tag
  • uploaded: Upload timestamp
  • checksums: File integrity checksums
  • httpMetadata: HTTP headers and metadata
list.ts
ExpandClose

_39
import type { APIRoute } from "astro";
_39
_39
export const GET: APIRoute = async ({ request, locals }) => {
_39
try {
_39
// Check if bucket is available
_39
const bucket = locals.runtime.env.CLOUD_FILES;
_39
if (!bucket) {
_39
return new Response("Cloud storage not configured", { status: 500 });
_39
}
_39
_39
const options = { limit: 500 };
_39
const listed = await bucket.list(options);
_39
let truncated = listed.truncated;
_39
_39
// Paging through the files
_39
// @ts-ignore
_39
let cursor = truncated ? listed.cursor : undefined;
_39
_39
while (truncated) {
_39
const next = await bucket.list({
_39
...options,
_39
cursor: cursor,
_39
});
_39
listed.objects.push(...next.objects);
_39
_39
truncated = next.truncated;
_39
// @ts-ignore
_39
cursor = next.cursor;
_39
}
_39
_39
// Return the files as a JSON object
_39
return new Response(JSON.stringify(listed.objects), {
_39
headers: { "Content-Type": "application/json" },
_39
});
_39
} catch (error) {
_39
console.error("Error listing assets:", error);
_39
return new Response("Failed to list assets", { status: 500 });
_39
}
_39
};