I am trying to implement S3 file hosting at wasabi using the examples from their docs. While setting up credentials with SharedIniFileCredentials
works great in Node, I would need to use the same functionality inside the browser.
Here, I get the following error
aws_sdk__WEBPACK_IMPORTED_MODULE_1___default(...).SharedIniFileCredentials is not a constructor
This is my code (that runs great inside node, but throws an error inside a React component):
import AWS from 'aws-sdk';
export const createS3Client = (): AWS.S3 => {
const credentials = new AWS.SharedIniFileCredentials({ profile: 'wasabi' });
AWS.config.credentials = credentials;
AWS.config.credentials.accessKeyId = process.env.NX_WASABI_KEY;
AWS.config.credentials.secretAccessKey = process.env.NX_WASABI_SECRET;
AWS.config.region = process.env.NX_WASABI_REGION;
const ep = new AWS.Endpoint(process.env.NX_WASABI_ENDPOINT);
const s3 = new AWS.S3({ endpoint: ep });
return s3;
};
export const getFile = async (key: string): Promise<Buffer> => {
const s3 = createS3Client();
const params = {
Bucket: process.env.NX_WASABI_BUCKET,
Key: key,
};
const data = await s3.getObject(params).promise();
return data.Body as Buffer;
};
The main reason why I am trying to do this is because I want to load images stored inside a bucket that are not publicly available into a FE (React) component.
This is the component in question:
import { useEffect, useState } from 'react';
import { getFile } from '../../lib/wasabi';
import Image from 'next/image';
import styles from './PaletteImage.module.scss';
interface Props {
name: string;
source: string;
}
const PaletteImage = ({ name, source }: Props) => {
const [isLoading, setIsLoading] = useState(true); // component needs to load image data on mount
const [error, setError] = useState<string>();
const [base64, setBase64] = useState<string>();
useEffect(() => {
const parseImage = async () => {
try {
const buffer = await getFile(source);
setBase64(buffer.toString('base64'));
} catch (e) {
setError(e.message);
} finally {
setIsLoading(false);
}
};
parseImage();
}, []);
return (
<div className={styles.imageContainer}>
{isLoading ? (
'loading'
) : error ? (
error
) : (
<Image
alt={name}
layout="fill"
objectFit="contain"
objectPosition="left top"
src={`data:image/jpeg;base64, ${base64}`}
/>
)}
</div>
);
};
export default PaletteImage;
Thanks for the help.
You will need to use an alternative to AWS.SharedIniFileCredentials since the browser scripts of the AWS JavaScript SDK do not support it and the browser version of the SDK can't also get access to AWS.SharedIniFileCredentials that is meant to retrieve credentials from the local file system.
Options available include CognitoIdentityCredentials or Web Federated Identity. See: https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-browser.html
I suggest you refer to the following documentation for the AWS Javascript SDK:
https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/js-sdk-dv-v2.pdf#setting-credentials-browser
Cheers