File uploads
This process will be split in 3 parts:
add a
contact_imagecolumn to thecontactstableadd file uploads capability to React
add file receiving capability to Express
Migration
In a first instance, we need to create a new migration script for contacts. Put it in back/migrations, call it 003-images.sql:
--------------------------------------------------------------------------------
-- Up
--------------------------------------------------------------------------------
ALTER TABLE contacts RENAME TO old_contacts;
CREATE TABLE contacts (
contact_id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
email TEXT,
author_id TEXT,
date TEXT,
image TEXT,
FOREIGN KEY(author_id) REFERENCES users(auth0_sub)
);
-- copy old data in new table
-- all previous contacts are for the first user
INSERT INTO contacts (contact_id, name, email, date, author_id) SELECT contact_id, name, email, date, author_id FROM old_contacts;
-- remove previous table
DROP TABLE old_contacts;
--------------------------------------------------------------------------------
-- Down
--------------------------------------------------------------------------------
ALTER TABLE contacts RENAME TO old_contacts;
CREATE TABLE contacts (
contact_id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
email TEXT,
author_id TEXT,
date TEXT,
FOREIGN KEY(author_id) REFERENCES users(auth0_sub)
);
-- delete new contacts:
DELETE FROM old_contacts WHERE author_id = "fakeId";
-- copy old data to previous table
INSERT INTO contacts (contact_id, name, email, date, author_id) SELECT contact_id, name, email, date, author_id FROM old_contacts;
DROP TABLE old_contacts;We're going to add the new property in db.js and controller.js. Since we're beginning to have a lot of properties, having a dozen ifs in updates can be very cumbersome. Let's create a little function that helps us. Put it in db.js:
Done! Let's see how to handle uploads now
Sending Uploads From React
We will:
add a file field to the create and update form
get the data from that field on submit
change the method of
fetchforupdateandcreateso it usesPOST(this is necessary for uploads).prepare an image field to receive the property
All fairly simple, so we're not going to waste a lot of time in explanations. We should still try to understand how a file input works:
the onSubmit above can be re-written more simply as
If the field has only one file (multiple not set), then we can do:
Lastly, the way to send files through fetch is like so:
For both the update and create form:
add a file input field called "contact_image_input"
<input type="file" name="contact_image_input"/>in each form's
onSubmitcapture the files array
change
fetch's method toPOSTappend the body
Then, in <Contact>, we'll add a div to show the image
(don't forget to also pass image={contact.image} when you use <Contact/>)
Here is a summary of the changes:
note: we're uploading the images in /back, so it's natural that we serve the images from there. Thus, the //localhost:8080/images/ in image sources
Your front-end is ready to send files
Receiving Uploads on Express
We will:
set Multer to receive images, and change some methods to
POST.store the images somewhere public, and get the path
send that path to the database
Doing file uploads by hand is tricky, so we'll use Multer. If you've followed all steps, we already installed it previously. If not, move to back and run
You can now use it with an express app like so:
a multer file looks like so:
fieldname: Field name specified in the formoriginalname: Name of the file on the user's computerencoding: Encoding type of the filemimetype: Mime type of the filesize: Size of the file in bytesdestination: The folder to which the file has been savedfilename: The name of the file within the destinationpath: The full path to the uploaded filebuffer: A Buffer of the entire file
We need to set it a multer upload point before create and update.
Since we want the images we're saving to be accessible to users, we need to store them in /public.
Add multer, and create an upload point:
Then, let's add it to the two methods. Add it after isLoggedIn (no need to process the image if the user isn't logged in). Don't forget to change gets to posts!
And bam! File uploads work
note: You'll notice that when you create or edit a contact, you need to refresh to see the image. It's not immediately there because we aren't changing the browser-side representation of the contact. This is not very elegant, but also not essential, and we can think about it later.
You might want to ignore the images uploaded by adding **/*public/images to your .gitignore. It's not necessary, and you should do it depending if you feel your images are part of your core website or not.
Last updated
Was this helpful?