- Print
- DarkLight
Use JavaScript to Create an Application
- Print
- DarkLight
The following procedures demonstrate how to create an application using the AWS SDK for JavaScript.
Install the AWS SDK for JavaScript v3
You must have Node.js 14 or later to use the AWS SDK for JavaScript. Use the following command to install the current version of the AWS SDK for JavaScript using npm: npm install @aws-sdk/client-s3
.
Configure AWS (JavaScript)
Follow this procedure to create a named profile to access Backblaze B2 Cloud Storage; this allows you to easily access Backblaze B2 and alternative Amazon Simple Storage Service (Amazon S3)-compatible cloud object stores. You can also configure your default profile, set environment variables, or use any other configuration mechanism that is supported by JavaScript.
If you do not have the CLI, you can create a new AWS profile by creating or editing the AWS configuration files.
You can find the AWS credentials file at the following locations:
~/.aws/credentials
on Linux, macOS, or UnixC:\Users\USERNAME\.aws\credentials
on Windows
You can find the AWS configuration file at the following locations:
~/.aws/config
on Linux, macOS, or UnixC:\Users\USERNAME\.aws\config
on Windows
- Create the .aws directory and credentials file if they do not already exist, and add the following section to the file, substituting your credentials:
[b2tutorial] aws_access_key_id = <your_key_id> aws_secret_access_key = <your_application_key>
- Create the configuration file if it does not already exist, and add the following section, substituting the endpoint and region from your bucket details. The region is the portion of the bucket endpoint after
s3.
and before.backblazeb2.com
, for example,us-west-004
:[profile b2tutorial] endpoint_url = https://<your_bucket_endpoint> region = <region_from_your_bucket_endpoint>
The
endpoint_url
value must start withhttps://
. If you omit this, your application exits with anInvalid URL
error.
List Existing Buckets (JavaScript)
The simplest Amazon S3 action is List Buckets. It requires no parameters and returns a list of all of the buckets within the account.
- Create a file called
index.js
, and add the the following content:import { S3Client, ListBucketsCommand, CreateBucketCommand, PutObjectCommand } from "@aws-sdk/client-s3"; import { loadSharedConfigFiles } from '@aws-sdk/shared-ini-file-loader'; import fs from 'fs'; import path from 'path'; // Profile in the AWS config and credentials files const profile = 'b2tutorial'; // When using a non-default profile with the AWS SDK for // JavaScript v3, we have to explicitly load the profile's // configuration and credentials from the AWS config files. // If you are using the default profile, you do not need the // following three lines of code. const sharedConfigFiles = await loadSharedConfigFiles(); const config = sharedConfigFiles.configFile[profile]; const credentials = sharedConfigFiles.credentialsFile[profile]; // Initialize the B2 Client from the profile. // If you are using the default profile, // you can create the client with no arguments, i.e. // // const b2 = new S3Client(); // const b2 = new S3Client({ credentials: { accessKeyId: credentials.aws_access_key_id, secretAccessKey: credentials.aws_secret_access_key, }, region: config.region, endpoint: config.endpoint_url, }); // Function to list all buckets const listBuckets = async () => { try { const response = await b2.send(new ListBucketsCommand({})); console.log('Buckets in account:'); response.Buckets.forEach(bucket => { console.log(bucket.Name); }); } catch (err) { console.error("Error listing buckets:", err); throw err; } }; await listBuckets();
The app creates an S3Client object, passing the credentials and the endpoint for the profile. The app then sends a
ListBucketsCommand
to Backblaze B2. The response includes a list ofBucket
objects. Finally, usingforEach
, the app iterates through the list, printing each bucket's name. - Run the application using the following code:
node index.js
An output similar to the following example is returned:
Buckets in account: my-unique-bucket-name
Create a Private Bucket (JavaScript)
You already created a public bucket in the UI. Follow this procedure to use the Amazon S3 'Create Bucket' action to create a private bucket programmatically.
- Add the following code to
index.js
, immediately after the functionlistBuckets
, and replace the bucket name with a unique name:// The bucket to create or use const bucketName = 'another-unique-bucket-name'; // Function to create a new private bucket const createBucket = async (bucketName) => { console.log(`\nTrying to create bucket: ${bucketName}`); try { const response = await b2.send(new CreateBucketCommand({ Bucket: bucketName, ACL: 'private', })); console.log(`Success! Response is: ${JSON.stringify(response, null, 2)}`); } catch (err) { if (err.name === 'BucketAlreadyOwnedByYou') { console.log(`You already created ${bucketName}. \nCarrying on...`); } else if (err.name === 'BucketAlreadyExists') { console.log(`Bucket already exists in another account: ${bucketName}\nExiting.`); process.exit(1); } else { console.error("Error creating bucket:", err); throw err; } } };
- Add the following code at the bottom of the file, after the call to
listBuckets()
:await createBucket(bucketName);
The app sends a
CreateBucketCommand
to Backblaze B2 with the bucket name and the canned ACL valueprivate
, and displays the resulting response. The bucket may already exist, in which caseb2.send()
throws an exception. The exception's class indicates whether the bucket is owned by your account. If so, then the app displays an appropriate message and continues to the next step; otherwise, the app exits with an error. - Add the following code to run the app again:
node index.js
An output similar to the following example is returned:
Buckets in account: my-unique-bucket-name Trying to create bucket: another-unique-bucket-name Success! Response is: { "$metadata": { "httpStatusCode": 200, "requestId": "0728db53ff11c0ff", "extendedRequestId": "aMRU1W2YlOXAzzzXuY9tmhDQgZPpjQGKD", "attempts": 1, "totalRetryDelay": 0 }, "Location": "/another-unique-bucket-name" }
If the bucket already exists in another account, the following message is returned:
Buckets in account: my-unique-bucket-name Trying to create bucket: tester Bucket already exists in another account: tester Exiting.
If you encounter this error, change the bucket name and try again. Repeat until you find a unique bucket name.
- After the bucket is created, run the following code again:
node index.js
The following output is returned, indicating that the exception was handled:
Buckets in account: another-unique-bucket-name my-unique-bucket-name Trying to create bucket: another-unique-bucket-name You already created another-unique-bucket-name. Carrying on...
- Return to the bucket listing in the UI and refresh the page. The new private bucket is listed.
Upload a File to a Bucket (JavaScript)
You can upload a file to the private bucket using the Amazon S3 PutObjectCommand.
- Add the following code to
index.js
, immediately after the functioncreateBucket
, and replace the path with the path of your file to upload:// Replace with your local file path const filePath = './myimage.png'; // Function to upload a file to a bucket const uploadFile = async (bucketName, filePath) => { console.log(`Uploading: ${filePath}`); try { const fileStream = fs.createReadStream(filePath); const keyName = path.basename(filePath); const response = await b2.send(new PutObjectCommand({ Bucket: bucketName, Key: keyName, Body: fileStream, })); console.log(`Success! Response is: ${JSON.stringify(response, null, 2)}`); } catch (err) { console.error("Error uploading file:", err); throw err; } };
- Add the following code at the bottom of the file, after the call to
createBucket()
:await uploadFile(bucketName, filePath);
This section of code sends a
PutObjectCommand
object containing the name of the bucket that the app just created with the file content and a key set to the file name from the specified path. The response object contains several properties, includingETag
andVersionId
. - Enter the following code to run the app again:
node index.js
An output similar to the following example is returned.
Buckets in account: another-unique-bucket-name my-unique-bucket-name Trying to create bucket: another-unique-bucket-name You already created another-unique-bucket-name. Carrying on... Uploading: ./myimage.png Success! Response is: { "$metadata": { "httpStatusCode": 200, "requestId": "117b965cfde1f064", "extendedRequestId": "aMZk1dWZPOdIzbzVDY89mOzQJZMRjHmLX", "attempts": 1, "totalRetryDelay": 0 }, "ETag": "\"c9f8dc28075a308a50c30b78438fcf00\"", "VersionId": "4_z61c50fc9b3052c3f941d0c1b_f1109a5354a3cbf95_d20240805_m175830_c004_v0402025_t0007_u01722880710898" }
Etag and VersionId Output (JavaScript)
The Etag
value identifies a specific version of the file's content. Etag
is a standard HTTP header that is included when clients download files from Backblaze B2. Etag
enables caches to be more efficient and save bandwidth because a web server does not need to resend a full response if the content was not changed. VersionId
identifies a specific version of the file within Backblaze B2. If a file is uploaded to an existing key in a bucket, a new version of the file is stored even if the file content is the same.
To see the difference between ETag
and VersionId
, run the 'upload file' commands a second time and upload the same file content to the same bucket and key. The ETag
is the same since the content has not changed, but a new VersionId
is returned.
An output similar to the following example is returned:
Buckets in account: another-unique-bucket-name my-unique-bucket-name Trying to create bucket: another-unique-bucket-name You already created another-unique-bucket-name. Carrying on... Uploading: ./myimage.png Success! Response is: { "$metadata": { "httpStatusCode": 200, "requestId": "117b965cfde1f064", "extendedRequestId": "aMZk1dWZPOdIzbzVDY89mOzQJZMRjHmLX", "attempts": 1, "totalRetryDelay": 0 }, "ETag": "\"c9f8dc28075a308a50c30b78438fcf00\"", "VersionId": "4_z61c50fc9b3052c3f941d0c1b_f1007e901208228d6_d20240805_m182932_c004_v0402005_t0038_u01722882572248" }
Use PutObjectCommand
to upload a single file. To upload multiple files, your application must build a list of files to upload and iterate through the list.
Browse Files (JavaScript)
In the Backblaze web console, navigate to your private bucket on the Browse Files page. Your file is displayed with a (2) next to the filename.
If you click the (2), and click one of the file versions, you will see that the Fguid matches the VersionId that was returned when the file was created.
There is also no File Info for this file. The Backblaze web console set the src_last_modified_millis attribute for the file that you uploaded earlier, but you did not specify one when you uploaded the file.
Click one of the URLs to open it in the browser. You cannot access the file because it is in a private bucket. The S3-Compatible API returns the following XML-formatted error for the Amazon S3 URL.
<Error>
<Code>UnauthorizedAccess</Code>
<Message>bucket is not authorized: another-unique-bucket-name</Message>
</Error>
The Native API returns a similar, JSON-formatted error for the Native and Friendly URLs:
{
"code": "unauthorized",
"message": "",
"status": 401
}