Uploading a File to a Rails Backend

Source: Pexels

Uploading a file is an integral part to the user experience on any web application. Common uses for file uploads are uploading images to set as a user avatar, submitting a resume, and submitting assignments. How can you accomplish allowing a user to submit a file from the frontend and sending it to your Rails backend? This guide will walk you through setting up the form on the frontend using React and receiving the response in the backend with Ruby on Rails.

<form onSubmit={handleFormSubmit}>
<input
type="file"
onChange={(e) => setSelectedFile(e.target.files[0])}
/>
<button>Upload</button>
</form>

This will create a default file upload form that you have probably seen before on a web page. With every change in the file uploaded by the user, we are saving it to the state called “selectedFile”. Now, we will need to write the handling function for submitting the file upload.

const handleFormSubmit = (e) {
e.preventDefault();
//creating the FormData object to be sent in an HTTP request
let formData = new FormData();
//appending the file key with the uploaded file in the FormData
//object
formData.append("file", selectedFile);
// POST request for uploaded files
fetch(your-post-url, {
method: "POST",
body: formData
})
.then(res => res.json())
.then(data => rest of frontend logic);
}

The FormData datatype is important because it easily bundles the key/value pairs in a form and allows the data to be sent in an HTTP request. By using FormData, you also do not need to specify content-type in your headers as it uses the same format as “multipart/form-data”.

class FileController < ApplicationController
def create
file = File.create({
file: params[:file]
the remaining params
})
end
render json: file, status: :created
end

Within your controller, you would create a new instance of your file class using params[:file] like you would with any other params. My preferred way to handle receiving file uploads and storing them in a database is with Active Storage with an Amazon S3 Bucket.

(byebug) params[:file]
#<ActionDispatch::Http::UploadedFile:0x00007fa44422c758 @tempfile=#<Tempfile:/tmp/RackMultipart20220420-12962-1bt65j0.jpg>, @original_filename="07CAT-STRIPES-mediumSquareAt3X-v2.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"image\"; filename=\"07CAT-STRIPES-mediumSquareAt3X-v2.jpg\"\r\nContent-Type: image/jpeg\r\n">

In my example, I placed a byebug in the create action and inspected the object being sent. As you can see, there are a lot of useful attributes including the file name, content type, and the Tempfile object. These attributes will be critical for Active Storage to store your files and attach them to its associated records.

This blog post covers the bare minimum to allowing users to upload a file from a React frontend to your Rails backend. I would strongly recommended using Active Storage to facilitate file uploads to an external cloud storage service (Amazon S3, Microsoft Azure, Google Cloud Storage) and associating those files to your Active Record objects. A great guide to getting all of this set up can be found here.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store