Current section: File Upload 4 exercises

Intro to File Upload


00:00 Let's talk about file uploads. Before we get into this, I want to mention that Kelly, your coworker, has done some pretty cool things to allow us to have images on our routes. So she made a resource route for us. Feel free to dive into this and look at that if you like.

00:18 But again, you've learned about resource routes, it's just a route that does not export a default. Here we've got the loader, we take the image ID, we look up that image in the database, which we're going to be adding images to soon. And then we take all that information,

00:36 we create a read stream from the file system where the image is stored, and then we send that to the client like an image is sent. Like I said, resource routes are just the coolest things. So Kelly did that for us. You can feel free, if you want to like delete this and re-implement it from scratch,

00:53 probably a good thing to know how to do. But yeah, we're not going to be doing that today. So let's talk about how we get files from the user's computer to our server. And that is done using forms, ta-da! So with forms, the only change that you need to make

01:12 to support file uploads is you need to specify the encoding type is multi-part form data. That way it can take the form and stream it in different chunks, reasonably sized chunks to the server. And then you can use a input type file and the browser will have a file picker

01:31 and it'll be awesome. Additionally, you can actually have multiple of those. So a user can select multiple files and that will give you what's called a file list, at least on the client. And you can use that to do all sorts of things. Each one of those files is a file object.

01:50 They'll have a name and a size and a MIME type and last modified information like that. Now you don't actually on the client have access to the file system. So this is just like a sort of mini proxy that gives you just enough information to be able to do stuff like this where I can change the image

02:07 and I can access the file itself to be able to display it so they get some sort of preview of what options they have there. So then you also have the accept attribute which we're gonna be using today so that you can say, hey, I accept files that are the MIME type image

02:27 slash anything. So any type of image I'm good to handle. So the accept attribute is quite handy also. On the server side of things, you've got to deal with streams and streams are awesome. You can do all kinds of things. Remember the problem is that your file could be like multiple gigabytes if you're uploading a video or something.

02:46 And so we have to take it into little chunks and send those little chunks over time. And then on the server, we take that stream and we just process each little chunk one by one. That process is rather involved. I wouldn't recommend writing all of that yourself and you don't have to. Luckily for us, we have Remix

03:03 which has implemented some handlers for us for doing this sort of thing. So whereas before we had await, whoops, await request form data to get our form data, now we actually get our form data using this parse multiple part form data.

03:21 You can feel free to dive into the implementation but it is actually rather involved in like the dependency of the dependency that we're using, but it's pretty cool. So with the parse multiple part form data, you can provide an upload handler and that upload handler can be custom. You can make your own

03:41 and that just allows you to handle chunks as they come in. And you can either stream that to S3 or Cognery or wherever you want to host your images. You can stream it straight to the file system. There's also a create file system upload handler. So Remix will do that for you.

04:00 We're gonna use that memory upload handler. That's what I use when I am supporting files that are of a sufficient size to fit within the memory and use cases of my app. This is drastically simpler and it works for many, many cases. But again, you can make your own file handlers and there are examples that you can look at

04:18 how to have this stream up to some other service if that's what you're gonna be using. Once that is all done and parsed, then what you get when you say, hey, I wanna get that thing that is the file upload, what you get back from that is whatever the upload handler returns for each one of those processed entries.

04:38 And so in the case of the memory upload handler, you're gonna get a file object back and then you can use that. You'll have the whole blob and everything. You can use that to save it in a database or save it to the file system, whatever you wanna do with that. So that is, yeah, that's everything that I think you need to know about file uploads before we get started on this exercise.

04:59 Definitely something that many apps need and I really like the way that we do it here in the Epic Stack with Remix. So let's get going on this one.