Gonsa02
Gonsa02

Reputation: 351

How to know the extension of a file to be able to download it correctly in react (javascript)?

I am trying to download files. The problem is that I do not know how to get its extension and they load me incorrectly, on the other hand if when I put its name I write the extension (knowing what it is) it is downloaded correctly. The problem is that in the app you don't know what type of file comes to you, you can get a pdf, a jpg, ... What I do is make a request from the NodeJS backend to AWS S3 to receive the file and I send it to the frontend of react.

Here is the backend code:

routerTrainer.get("/download-training", async (req, res) => {
  const { training_id } = req.headers;

  let training = await Training.findOne({
    where: { id: training_id },
  });

  if (training) {
    let readStream = getTrainingS3(`${training.file_id}`);
    readStream.on('close', () => {
      res.end()
    })
    readStream.pipe(res);
  }
});

And here is the clients Code:

const downloadTraining = async (id) => {
    fetch(`${serverPath}/download-training`, {
      headers: {
        training_id: id,
      },
    })
      .then((res) => res.blob())
      .then((blob) => {
        const link = document.createElement("a");
        link.href = URL.createObjectURL(blob);
        link.setAttribute("download", `here_is_where_I_need_to_put_extension_to_get_it_working`);
        document.body.appendChild(link);
        link.click();
      });
  };

Please if anyone has any ideas on how to do it, I would be very grateful for your help.

Upvotes: 2

Views: 877

Answers (1)

Kamil Janowski
Kamil Janowski

Reputation: 2025

If I understand correctly, your file is in S3. This makes your approach invalid here. S3 has a very specific approach to file uploads and downloads and that's through "pre-signed URLs" and if you used that standard approach, you wouldn't be facing the problem you're facing in the first place.

More about pre-signed URLs: https://aws.amazon.com/blogs/developer/generate-presigned-url-modular-aws-sdk-javascript/

But the general idea is the following:

  1. UI makes a request to your backend
  2. Backend generates a pre-signed S3 URL (note that for this to work properly, you need to have IAM permission to Get Object). This is basically a special S3 URL that works only for the next few minutes and allows the user to either upload or download file (depending on how you configured the pre-signed url)
  3. Backend sends a response back to UI with the generated URL
  4. UI executes a follow-up request to now download the file. So, the download really happens directly from S3, skipping your webapp altogether. This makes it much easier later for you to scale up your application too. Especially since... Node.js apps don't really deal too well with too much load in parallel due to the fact that everything runs in a single thread and all.

So, to answer the original question, your file on S3 probably has an extension. When you generate the pre-signed URL, that URL will contain the full file name along with the extension, so you don't really have to worry about it.

Upvotes: 2

Related Questions