Not sure if you want to save the attachments indefinitely. Nonetheless, one option could be that you use an API Gateway. You will need to handle authentication and authorization yourself. You could use a token for instance that you can compare with a token in your database. The token grants access to one certain file and is part of the request URL (or it's request headers). But first on how to generate the "pre-signed URL":
- when an attachment is uploaded to S3 you generate a token, i.e. JWT token, with the file name.
- Save the token in a DynamoDB, possibly with an expiry date, if needed
- Return the API Gateway URL and the generated token to the user, e.g. https://get-your-attachment.io/download?token=123
- If the token expires use DynamoDB streams to find the file in S3 and remove it from S3 to have it cleaned up
If a user wants to download a file, they open the URL provided in step 3. The API Gateway calls an authorization Lambda. This Lambda checks that the token is still in the DynamoDB. If so, the request triggers another Lambda function which will extract the file name out of the token and return the file. You have to return the file encoded, set the response headers properly and take care of the service limits.
If the download can only be done from within your app and the link cannot be shared nor used outside of the app, then you could skip returning the file through the API Gateway. Authorization will stay as described above. But instead of returning the file, the Lambda function returns a pre-signed URL, valid for maybe 10 minutes. Your app uses the URL for another request and receives the file from S3.
As for the second part of your question on how to download the files as simple fetch(preSignedS3URL)
will be enough.