Handling File Uploads On Backend

When uploading a file, one question one has to decide on is where is the file stored? This post assumes we are going to store our upload files on AWS S3.

If we pick S3 we get a three-node issue: you have the end user, say in India, your server, say in Europe, and S3 bucket, say in US. When uploading a file, we do not want the file to travel from user’s machine (India) to our server (Europe) and then to S3(US), as that is wasteful, and also slow, especially because upload stuff, images, videos tend to be in megabytes.

What we want the file to go directly from user to S3. Which brings us to the question of access control. We can not give write access to our S3 buckets to everyone in the world. We have to give controlled access to upload, our backend must be able to verify that user is logged in, for example. Our backend may also have to decide what file types user can upload, or what destination it should go on (the url of the uploaded file).

S3 has a concept of pre-signed request. The backend, calls a S3 api, and you can get a pre-authenticated URL back, which can be used for limited time, to make POST or PUT request and update its content.

In order to call the API, you already need to create the S3 object, which means you must already know the file path, and file type (mime-type).

If you already know the file path, eg the image the user is going to upload is their profile picture, and the mime type, and say the URL is going to be /profile/{username}.jpg, then you can create the pre-signed URL and send to Elm for upload on page load.

But in many cases you may not know the file name or extension, say you want user to upload file of any type, jpeg, png, gif, then on page load you can not include the signed-url, and will have to wait for file select or file drop event, inspect the dropped or selected file, figure out the name and mime type, send a request to backend from frontend to get a pre-signed URL, and then do the PUT or POST request from browser. At the end of successful upload you may want to call the backend once again, say to commit the fact that profile image has changed, and new URL should be stored in user table so future page views sees the latest uploaded image.

When allowing cross domain requests, CORS headers must be also be configured on the bucket. You may want to configure it as strict as needed, only your own domain and only the methods you are planning to allow browser to make.

Table Of Content

What is Realm?

A Bit On Motivation

Routing is Hard

What does Realm do?

Backend Data And Type Safety


Quick Start Realm Tutorial

In Depth Tutorial (not ready)

Hello Rust
Hello Elm
Hello Static Files
Hello Server Side Rendering
Pre-Commit Hooks

Routing, Request And Response

Frontend, Data, Navigation, And APIs

How To Guides

File Upload

Backend: S3 File Upload
Authenticated File Serving
Frontend: Uploading Files From Elm

How to use storybook?

How to implement “loading..”?









Environment Variables

Internals - Only for Realm Developers, not Users

“Realm DATA”
iFrame Controller
Shutdown Routine
Testing Internals

Change Log

Get Realm Starter Working

Transparent Offline Feature

How to make http requests in Realm?


Replay Testing

Tutorial: ToDo App

Realm Testing

Enhance Realm Starter

Double Load Issue

Deploy To Heroku Button

End failure

Realm-Starter Github Template

Proposal: Tracker And Visit

Proposal: Activity Store

Proposal: Bundling

Proposal: Retry On Network Error

Storybook: Editable JSON

Storybook: Notes

Storybook: Reference



Change Log

How to Publish


Code Snippets

Skip rustfmt For Some Section

Close Modal Dialog When Clicked Outside

Ignoring Lints In Python

Ignoring Lints (clippy and rustc warnings) In Rust

Handle DateTime in Rust & Elm

Handle CiText value read in Rust

Transport Enum Type to and fro Rust/Elm through JSON