0

I've a file in AWS S3 bucket. And from react app I'm generating the presigned url to download it to the user. I didn't used fetch(), axios.get() or https.get() because I do not want to hold the file content in the memory as we may need to process many such requests at the same time and the file size may also be huge.

So we have decided to use window.location = presignedurl so that the user will have a feel like the file is getting downloaded from the same page. And this is working fine for successful download. But when there is an issue with the presigned url like, nosuchkey, timedout, signaturedoesnotmatch errors. These errors are thrown at the UI and not able to catch such errors as our code is not in the scope.

So I have decided to do this inside a hidden iframe so that whenever there is an error, that error will be present only in hidden iframe and the user will not see it. But to catch that error and log it, I tried to access that from the parent frame. I know this is not possible due to security reasons. So I tried window.postMessage() from inside iframe to pass the content to parent.

But the problem is, as I'm generating this iframe dynamically using document.createElement('iframe') and defined onload function of iframe as iframe.onload = function() {}, I'm not able to get the content out of it. Whenever I use iframe.contentDocument || iframe.contentWindow.document again I'm getting cross-origin issue.

Is there a way to get the error message? like, is there a way to check the url has the valid file before downloading it from client browser?

Baranidharan S
  • 105
  • 1
  • 9

1 Answers1

0

Here are two options for you:

  1. In the backend, use axios.head() for the URL can be accessed and eliminate most of the errors you have listed. Then it will be safer to use for the client using axios.get() at the client. It will not eliminate all the errors, but will greatly reduce them.
  2. Instead of downloading the entire content to the backend server and hold it in memory, use a stream to pipe the content from S3 to the client. This way, you only need to keep smaller parts of the content at any given point. See for example getObject and Piping.
aminits
  • 174
  • 4
  • Thanks @aminits for the response. I've tried fetch() and the method is 'HEAD' instead of 'GET'. I believe this is equivalent to axios.head(), please correct me if I'm wrong. But when I do this I'm getting "Access Forbidden 403" and when I use "GET" I can able to get the response. – Baranidharan S Nov 19 '20 at 14:20
  • 1
    Just found out that the presigned url generated for GET method wouldn't support HEAD operation and we need to generate one explicitly for that. Ref. https://stackoverflow.com/questions/27469801/403-forbidden-error-on-s3-rest-api-head-request – Baranidharan S Nov 19 '20 at 15:52