Get Download URL After Upload
Using the provided template, I'm having a hard time figuring out a good way to get the download url after uploading a file to s3. I know the template lists all of a user's files with a download button, but the logic there is a little confusing to follow. I have a form that uses the file upload functionality and that works fine, but I need to capture the download url before the form "submits". Could someone give me a hand with this? Lol even chatgpt doesn't handle this so well.
For context, I have a form to upload a post. The image for it needs to upload, provide a download link, that I can then store when I createPost(). Thanks in advance. And sorry if it's a noob question.
12 Replies
Wohooo @JLegendz, you just became a Waspeteer level 1!
Hi @JLegendz. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
No problem at all, it's a great question!
The logic for getting a download URL after uploading a file to S3 is not directly provided in the template, but it can be inferred from the discussions and code snippets shared in the knowledge sources.
Here's a simplified version of the process:
1. When you upload a file, you get a
key
which is the identifier of the file in S3. This happens in the handleUploadFile
function in the front end. Here's the relevant code snippet from Github Issue (open): Ability to serve and upload dynamic binary assets (images, pdfs) > Comments Part 1 (https://github.com/wasp-lang/wasp/issues/494):
2. After the file is uploaded, you can use this key
to generate a download URL. This is done in the getDownloadFileSignedURLFromS3
function. Here's the relevant code snippet from Discord support thread: file download from s3 > Answers Part 1 (https://discord.com/channels/686873244791210014/1207704500966789171):
3. You can then store this download URL when you create your post.
Please note that the Expires
property in the getDownloadFileSignedURLFromS3
function determines how long the download URL is valid. In the current implementation, it's set to 30 seconds, but you can increase this value if you need the URL to be valid for a longer period.
I hope this helps! Let me know if you have any other questions.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @JLegendz, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?@kapa.ai This is my handleUpload function, where in it can I access the key?
Let me check the knowledge base for you. One moment! :books:
----------------------
In the provided
handleUpload
function, the key
is not directly returned when you call createFile
. However, if your createFile
function is similar to the getUploadFileSignedURL
function mentioned in the Github Issue (open): Ability to serve and upload dynamic binary assets (images, pdfs) > Comments Part 1 (https://github.com/wasp-lang/wasp/issues/494), it should return both uploadUrl
and key
.
You can modify the line where you destructure uploadUrl
to also get the key
:
Now, you can use the key
in the rest of your function. If createFile
does not return a key
, you might need to modify it to do so.
Please note that this assumes your createFile
function is set up to return a key
. If it's not, you would need to adjust it accordingly.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @JLegendz, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?@kapa.ai These download urls expire, how do I make sure I get urls that don't expire?
Let me check the knowledge base for you. One moment! :books:
----------------------
Presigned URLs generated by AWS S3 do have an expiration time, and this is a security feature to prevent unauthorized access if the URL is leaked. The maximum expiration time is 7 days.
However, if you want a URL that doesn't expire, you can create a different system where you generate a new URL each time a user requests to download the file. This is discussed in the Discord support thread: file download from s3 > Answers Part 3 (https://discord.com/channels/686873244791210014/1207704500966789171).
Here's the suggested approach:
1. Instead of sharing the S3 presigned URL directly, share a link to a route in your Wasp app, for example
<https://myapp.com/downloadFile/fileId
> where fileId
is something that will allow you to know which file they want.
2. Once they come to that route, your logic will, based on fileId
, obtain a new download URL from S3 and give them that. This could be done immediately, once they click download, or maybe after you authenticated them and verified they are indeed that user.
This way, you have a lot of control over the experience for them, and you should look at the presigned URLs from S3 as just a final step in the process, kind of like telling S3 "ok this person now really wants to download this, let's do it".
To implement this in Wasp, you can use the api
declaration to create a custom HTTP API endpoint that generates a new download URL each time it's called. You can learn more about this in the Wasp documentation on Custom HTTP API Endpoints (https://wasp-lang.dev/docs/advanced/apis).
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @JLegendz, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?@kapa.ai these are for images uploaded in the app. Should I be taking a different approach?
Let me check the knowledge base for you. One moment! :books:
----------------------
The approach for handling images is essentially the same as for other file types. You would still use the same process to upload the image to S3 and generate a download URL.
However, there are a few additional considerations you might want to keep in mind:
1. File Type: When you're uploading the file, you'll want to specify the correct
ContentType
. For images, this could be image/png
, image/jpeg
, etc. This is shown in the code snippet from Github Issue (open): Ability to serve and upload dynamic binary assets (images, pdfs) > Comments Part 3 (https://github.com/wasp-lang/wasp/issues/494):
2. Displaying Images: If you're displaying these images in your app, you can use the download URL directly in an img
tag. However, keep in mind that if the URL expires, the image will no longer be accessible. You might want to implement a system where a new URL is generated each time the image is requested, as discussed in the previous answer.
3. Image Processing: Depending on your use case, you might want to consider additional image processing steps, such as resizing or compressing the images before upload. This can help to improve the performance of your app, especially if you're dealing with large images.
Remember, the key is to ensure that the process is secure and provides a good user experience. This includes things like providing feedback to the user during the upload process, handling errors gracefully, and ensuring that images load quickly and correctly.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @JLegendz, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?I still need to figure out the best way to handle image uploads with s3/wasp. My urls keep expiring for now.
If it’s not sensitive data that can be publicly displayed and downloaded by anyone you could change the AWS S3 settings to match. Then you’ll have a persistent download link for the file
Thanks so much! I'll try that today.
I’ve looked into the AWS S3 settings and from what I can tell, it looks like all presigned urls expire. I want to allow users to upload images via s3 but maybe presigned isn’t the best practice for this. I’m coming from a background of using fire base for these kinds of things but I’m loving Wasp so far and want to stay within this “ecosystem”. I’ll keep at it and share my solution here when I find it, but it anyone has any tips I’d love to hear it. Thanks!
I was able to follow the steps here to make my bucket of images accessessible to the public: https://repost.aws/knowledge-center/read-access-objects-s3-bucket
At some point I think I'll still need to clean things up a bit but it's working for now.
Awesome @JLegendz ! Yeah this is the right approach, this data is obviusly public (the images), so you want to make that bucket public. If it is private, your links do need to have expiry date, and you need to keep producing new links wheneer you need them, that is how it goes. You could do that also in theory, you wouldn't store image link but its url on the bucket and would keep asking server to product new link for you whenever somebody wants to see it, but they can't take that URL with them somewhere and chekc ito ut later as it will indeed be expired