Dealing with an AWS S3 bucket file not found error: A comprehensive guide

My image route uses a controller like this:

public getImage(request: Request, response: Response): Response {
    try {
        const key = request.params.key;
        const read = getFileStream(key);

        return read.pipe(response);
    } catch (error) {
        return response.status(404).json({
            message: 'Image not found.'
        });
    }
}

Additionally, I have the following function:

// aws.ts

export function getFileStream(fileKey: any) {
    const downloadParams = {
        Key: fileKey,
        Bucket: bucketName
    };

    return s3.getObject(downloadParams).createReadStream();
}

However, I encounter an issue when I provide a key that doesn't exist in the S3 bucket. The try/catch block does not handle this scenario, causing my app to crash with an 'Access denied' error code. How can I resolve this situation? Thank you! 😁

Answer №1

In order to ensure that the key refers to a valid object, I first validate it by retrieving the object data before attempting to access the object itself. If the object does not exist, an error is thrown which can be caught, as shown below:

// aws.ts

export async function getFileStream(key: string) {
    const downloadParams = {
        Key: key,
        Bucket: bucketName
    };

    try {
        // Check if object exists
        const head = await s3.headObject(downloadParams).promise();

        // Return the object
        return s3.getObject(downloadParams).createReadStream();
    } catch (headErr: any) {
        // Return null if an error occurs
        return null;
    }
}

Then, in the controller:

public async getFile(request: Request, response: Response) {
    const key = request.params.key;

    const read = await getFileStream(key);

    if (read != null) return read.pipe(response);
    else return response.sendStatus(404);
}

Make sure to include the list bucket option in your S3 policy, as it is required to use the headObject() method. Below is an example of the policy needed:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:DeleteObject",
                // The following actions are required
                "s3:GetObject",
                "s3:ListBucket",
            ],
            "Resource": [
                "arn:aws:s3:::YOUR-BUCKET-NAME-HERE",
                "arn:aws:s3:::YOUR-BUCKET-NAME-HERE/*"
            ]
        }
    ]
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to easily deactivate an input field within a MatFormField in Angular

I've come across similar questions on this topic, but none of the solutions seem to work for me as they rely on either AngularJS or JQuery. Within Angular 5, my goal is to disable the <input> within a <mat-form-field>: test.component.h ...

Adjusting the value of a mat-option depending on a condition in *ngIf

When working with my mat-option, I have two different sets of values to choose from: tempTime: TempOptions[] = [ { value: 100, viewValue: '100 points' }, { value: 200, viewValue: '200 points' } ]; tempTimesHighNumber: TempOpt ...

Encountering a sign-in issue with credentials in next-auth. The credential authorization process is resulting in a

I am currently facing an issue with deploying my Next.js project on Vercel. While the login functionality works perfectly in a development environment, I encounter difficulties when trying to sign in with credentials in Production, receiving a 401 error st ...

Angular Error TS2554: Received x arguments instead of the expected 0 on piped operators

I encountered an issue with Error TS2554: Expected 0 arguments, but got 4 when dealing with the observable getHappyDays(). The getHappyDays() Observable returns either Observable<HttpResponse<IHappyDays>> or Observable<HttpErrorResponse> ...

Can you provide input to the reducer function?

In the creator, an action is defined like this: export const actionCreators = { submitlink: (url: string) => <SubmitLinkAction>{ type: 'SUBMIT_LINK' } } In the component that calls it: public render() { return <div> ...

The success function in AJax does not properly execute on Safari browsers

Here is an example of my AJAX function: $.ajax({ url: "thankyou", type: "POST", data: arr, tryCount : 0, retryLimit : 3, success: function(response) { if(response == "Success"){ location.href = "/thankyou.html"; }else{console.l ...

What is the best way to display a 'confirmed' message on my registration page once a user has submitted their information?

I have set up a nodejs server and developed a registration page using HTML. When users click the submit button, the server I built receives the input data and validates it. If the user is successfully added to the database, I want to display a new message ...

Using TypeScript in React, how can I implement automation to increment a number column in a datatable?

My goal is to achieve a simple task: displaying the row numbers on a column of a Primereact DataTable component. The issue is that the only apparent way to do this involves adding a data field with indexes, which can get disorganized when sorting is appli ...

Live chat application experiencing issues with chat updates

I am currently developing a real-time chat application using socket.io for the server and React for the client-side code. Despite logging correct data in multiple consoles, I encountered an issue where new messages sent by one user are not automatically di ...

Using setTimeout() and clearTimeout() alongside Promises in TypeScript with strict mode and all annotations included

Many examples of timer implementations using Promises in JavaScript seem overly complex to me. I believe a simpler approach could be taken. However, I am looking for a solution specifically tailored for TypeScript with the "strict": true setting and all ne ...

When accessing NextJS '/', the index.js file fails to load any content

Hey there, I'm a beginner with Next.js and running into an issue where http://localhost:3000 doesn't seem to work when using client-side routing. However, it loads fine when I manually refresh the page. In my Header.js file, which handles naviga ...

Is the Prisma model not reachable through Prisma Client?

I'm currently attempting to retrieve a specific property of a Prisma model using Prisma Client. The model in question is related to restaurants and includes a reviews property that also corresponds with a separate Review model. schema.prisma file: // ...

Encountering a 'Page Not Found' Message when accessing a Node.js Lambda Microservice Serverless Express.js with Compression

I'm currently grappling with understanding how the compression nodejs library operates and why it's causing issues in my specific scenario. The code I've developed is intended to be executed on AWS Lambda running nodejs 6.10. Below is my in ...

The functionality of the Ionic 4 app differs from that of an Electron app

I've encountered an issue with my Ionic 4 capacitor app. While it functions properly on Android studio, I'm having trouble getting it to work on Electron. Any ideas on how to resolve this? Here are the steps I took to convert it to Electron: np ...

Convert your Node.js server URL hosted on AWS Elastic Beanstalk to HTTPS

Struggling to deploy my React JS app using AWS S3 bucket as I am new to the platform. The app communicates with a Node/Express server hosted on an Elastic Beanstalk environment. Encountered the error: Mixed Content: The page at 'https://myReactApp.s3. ...

Deploying a nodejs express application on an AWS Windows server

I successfully deployed my nodejs application on an AWS server with Windows Server as the operating system. The application is a basic express server running on HTTPS port 443. While I am able to access the application through localhost, unfortunately I am ...

Injecting Node (Express) files into controllers

Within my express application, I have a methods directory that houses a methods.js file. This file contains the common functions which I require in each controller. Content of methods.js: function helloworld() { return "Hello World" } Now, my task i ...

The compiler option 'esnext.array' does not provide support for utilizing the Array.prototype.flat() method

I'm facing an issue with getting my Angular 2 app to compile while using experimental JavaScript array features like the flat() method. To enable these features, I added the esnext.array option in the tsconfig.json file, so the lib section now includ ...

Converting an HTML page to PDF with Angular using jsPdf and Html2Canvas

[1st img of pdf generated with position -182, 0, image 208,298 ][1]Converting an HTML page to PDF in Angular 8+ using jspdf and Html2canvas has been a challenge. Only half of the page is successfully converted into PDF due to a scaling issue. Printing th ...

Using Mongoose, Express, and Node.js to send a server variable to an HTML page

I've encountered an issue while attempting to transfer a variable from my server.js file to HTML. Despite successfully passing the variable to another EJS file on a different route, I can't seem to display it within this specific EJS file. Strang ...