Skip to main content

AWS JavaScript SDK

This guide assumes that you have followed the steps in the Getting Started guide, and have the access keys available.

You may continue to use the AWS JS SDK as you normally would, but with the endpoint set to https://fly.storage.tigris.dev. Also make sure that s3ForcePathStyle is set to false.

import { S3Client } from "@aws-sdk/client-s3";

const S3 = new S3Client({
region: "auto",
endpoint: "https://fly.storage.tigris.dev",
s3ForcePathStyle: false,
});

Getting started

This example uses the AWS Node.js SDK v3 and reads the default credentials file or the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

import {
S3Client,
paginateListBuckets,
paginateListObjectsV2,
PutObjectCommand,
} from "@aws-sdk/client-s3";
import { readFile } from "node:fs/promises";

// listBuckets returns a list of all S3 buckets in the account with
// metadata such as creation date and owner.
export const listBuckets = async (S3) => {
const buckets = [];
for await (const page of paginateListBuckets({ client: S3 }, {})) {
if (page.Buckets) {
buckets.push(...page.Buckets);
}
}
return buckets;
};

// listObjects returns a list of all objects in a bucket. This only returns
// the keys of the objects, not the objects themselves. Customize the
// objects.push line to return more metadata about the objects.
export const listObjects = async (S3, bucketName) => {
const paginator = paginateListObjectsV2(
{ client: S3, pageSize: 100 },
{ Bucket: bucketName }
);
const objects = [];

for await (const page of paginator) {
if (page.Contents) {
objects.push(page.Contents.map((o) => o.Key)); // only get object keys
}
}
return objects;
};

// uploadObjectFromFS uploads a file from the local filesystem to an S3 bucket.
// This does not handle large files or multipart uploads.
export const uploadObjectFromFS = async (S3, bucket, key, filePath) => {
const command = new PutObjectCommand({
Bucket: bucket,
Key: key,
Body: await readFile(filePath),
});

const response = await S3.send(command);
return response;
};

const S3 = new S3Client({
region: "auto",
s3ForcePathStyle: false,
});

console.log("List buckets");
const buckets = await listBuckets(S3);
console.log("Buckets:", buckets);

console.log("List objects in a bucket");
const objects = await listObjects(S3, "tigris-example");
objects.forEach((objects, pageNum) => {
console.log(`Page ${pageNum + 1}:`, objects);
});

console.log("Upload an object");
const response = await uploadObjectFromFS(
S3,
"tigris-example",
"examples/js/getting-started.js",
"getting-started.js"
);
console.log("Upload response:", response);

Using presigned URLs

Presigned URLs can be used with the AWS Node.js SDK as follows:

import {
S3Client,
GetObjectCommand,
PutObjectCommand,
DeleteObjectCommand,
} from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

const S3 = new S3Client({
region: "auto",
s3ForcePathStyle: false,
});

// Presigned GET, allows users to download objects without making the bucket public.
console.log(
"GET:",
await getSignedUrl(
S3,
new GetObjectCommand({ Bucket: "tigris-example", Key: "bar.txt" }),
{ expiresIn: 3600 } // 1 hour
)
);

// Presigned PUT, allows users to upload objects without going through your server.
console.log(
"PUT:",
await getSignedUrl(
S3,
new PutObjectCommand({ Bucket: "tigris-example", Key: "bar.txt" }),
{ expiresIn: 3600 } // 1 hour
)
);

// Presigned DELETE, allows users to delete objects.
console.log(
"DELETE:",
await getSignedUrl(
S3,
new DeleteObjectCommand({ Bucket: "tigris-example", Key: "bar.txt" }),
{ expiresIn: 3600 } // 1 hour
)
);

You can now use the URL returned by the getSignedUrl function to download or upload objects to the bucket using the https package.

Renaming objects

Objects can be renamed in Tigris by attaching the X-Tigris-Rename header to a CopyObject request.

import {
S3Client,
PutObjectCommand,
CopyObjectCommand,
DeleteObjectCommand,
HeadObjectCommand,
} from "@aws-sdk/client-s3";
import { randomUUID } from "node:crypto";

export const renameObject = async (S3, bucket, oldKey, newKey) => {
S3.middlewareStack.add(
(next) => async (args) => {
// eslint-disable-next-line no-param-reassign
args.request.headers["X-Tigris-Rename"] = "true";
return next(args);
},
{
step: "build",
name: "renameObject",
tags: ["METADATA", "RENAME"],
}
);

const copyCommand = new CopyObjectCommand({
Bucket: bucket,
CopySource: `${bucket}/${oldKey}`,
Key: newKey,
});

await S3.send(copyCommand);

S3.middlewareStack.remove("renameObject");
};

const S3 = new S3Client({
region: "auto",
s3ForcePathStyle: false,
endpoint: "https://fly.storage.tigris.dev",
});

const bucket = "tigris-example";
const object = randomUUID();
const newObject = randomUUID();

let command = new PutObjectCommand({
Bucket: bucket,
Key: object,
Body: "Hello, Tigris!",
});
await S3.send(command);

console.log("Rename object");
await renameObject(S3, bucket, object, newObject);

command = new HeadObjectCommand({
Bucket: bucket,
Key: newObject,
});
await S3.send(command);

command = new DeleteObjectCommand({
Bucket: bucket,
Key: newObject,
});
await S3.send(command);