Upload photos to Amazon S3
Build an app to upload images to Amazon S3 and save URLs to an API.
Let's say we're Amazon, and want to upload some images for our books products. We'll build a tool to upload images to S3, and then save its URL to our API, all in 5 minutes.
0. Set up S3 credentials
Before uploading to S3, we'll have to add it as a resource. See S3 Integration on instructions. You'll need to make a S3 IAM user for Retool, as well as whitelist our domain in the S3 CORS settings.
Making a new S3 IAM user
Head over to IAM, make a new user, and call it retool-s3-uploader
. Only enable "programmatic access".
Hit "next" to grant the account permissions. The easiest is granting it full S3 permissions, but if you want, you can further restrict the permissions. You'll need to create a new policy, then attach the policy to the new user.
Here's an example JSON IAM policy that works. You'll need to change the YOUR_STATEMENT_ID
variable, as well as the YOUR_BUCKET_NAME_HERE
variable. Keep both the YOUR_BUCKET_NAME_HERE/*
and YOUR_BUCKET_NAME_HERE
- they're both necessary!
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketAcl",
"s3:GetBucketCORS",
"s3:GetBucketLocation",
"s3:GetBucketLogging",
"s3:GetBucketNotification",
"s3:GetBucketPolicy",
"s3:GetBucketWebsite",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectTagging",
"s3:PutObjectVersionAcl",
"s3:PutObjectVersionTagging"
],
"Resource": ["arn:aws:s3:::BUCKET_NAME", "arn:aws:s3:::BUCKET_NAME/*"]
}
]
}
Configuring CORS
Since we upload directly from your browser, you'll need to configure CORS (cross origin resource sharing). Open up the S3 bucket, click the Permissions tab, and then click CORS configuration, and paste in the following JSON, which lets Retool upload directly in to your S3 bucket from the browser.
Configuring CORS in the S3 console
If you are configuring CORS in the S3 console, you'll need to use JSON to create a CORS configuration. The new S3 console does not support XML CORS configurations.
[
{
"AllowedOrigins": ["https://*.retool.com"],
"AllowedMethods": ["PUT", "POST", "DELETE"],
"AllowedHeaders": ["*"]
},
{
"AllowedOrigins": ["*"],
"AllowedMethods": ["GET"]
}
]
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>https://*.retool.com</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
1. Upload images
Let's drag on a S3Uploader
from the right hand side, and then choose the right bucket:
Great! That's it — now let's try uploading a file by clicking on the button. After the file uploads, you should get a success notification. And now, you'll see that the .lastUploadedFileUrl
is now a S3 URL:
Great! Let's POST
that URL back to our API, so we can persist it in the database.
Max file upload size
Retool's max file upload size with a File Picker component is 40MB.
2. Save the S3 URL, part 1
See the right hand side of the S3Uploader
? There's a After Upload
callback. Let's click on it, and tell it to make a new query:
If we just want to persist images, we could just do a POST
back to our API, which is pretty easy.
3. Pulling in Products
Products
But realistically, we probably want to attach our images to a specific database record, like a Product
. To do that, we'll first have to pull in all our items. Let's write a SQL query:
select * from products order by id;
Great! Let's hit "run", and then "save" if it looks good:
After that, let's drag on a Table
from the right hand side. It'll be automatically populated with data from your last query (select * from products order by id
, in this case).
Great - table of products in. Now let's render the image itself from the image_url
in our database. To do that, let's drag in a Text
component from the right hand side, then set its value to be an <img>
tag:
<img src="{{table1.selectedRow.data.image_url}}" height="300" />
4. Save the S3 URL in our database, part 2
Nice! Now that we have a table of Products
, and we can preview each image, we're ready to change the image_url
. Let's do a PUT
back via our API, like the screenshot below.
And now... after it's PUT
, we want to refresh our SQL query, so it'll pull in the fresh data (including image_url
). So let's add that to the "On success, trigger these queries" section:
That's it! Now when we upload an image, it'll call the trigger, which'll PUT
back to our API. After that succeeds, it'll reload our SQL query to pull in our products again - this time with the updated image_url
.
5. Actually using it
This tool is now production-ready. If you don't want coworkers bugging you about uploading images to S3 + editing the database, just send them the link to this tool! If you give them specific permissions, they won't be able to edit the tool and change the queries - they'll just be able to use the tool you've created. Not bad for a few minutes of work!
Updated 6 months ago