Validating File Uploads with Zod Schema in a Web Application
00:00 So, we're going to need to update our schema to account for the image ID in the file and the alt text fields. So, let's add an image ID. That's simple enough. It's a string. It's optional because there may not be an image yet. The alt text, also a pretty simple thing.
00:17 That's also optional. You might want to say, alt text should always be required, but that's not super realistic and so we're not going to make it required. Yeah, you can get mad at me if you feel like it really should be. I can take it.
00:36 And then we're going to say instance of file. So, the interesting thing with the file is that because we're parsing this as a multi-part form data, before we get to the parse step, whatever this form data object is, is what we want to actually validate here.
00:53 And so, what's really cool about using the memory upload handler is that it turns the file from that stream that's being chunked into a file object. And so, you have to remember that the no editor schema is being used both in our action as
01:11 well as on the client. And so, by using file as our type, the instance of here, and by using a file on the server as well as on the client, we're actually getting this same validation on both sides. I think that's pretty cool.
01:30 This is a file type. Normally, this is going to end up being streamed somewhere and you'll get back a URL. And so, you'll have to do different validation whether it's on the server or on the client. So, in the client, you'll have to say it's got to be a file object. On the server, you've got to say it's got to be a URL to where that file lives and maybe some other metadata about it.
01:49 And in our case, because we're chunking it up into an in-memory file, we can do this. And we're not just doing that for the workshop. I'm not cheating you out on some experience or anything. This is how I do it. I put it in memory. Now, again, if you're accepting huge video uploads or something like that, then yeah,
02:08 you certainly wouldn't want to do things this way. But for a lot of the things that we're doing, just sticking it into a file in memory just temporarily works out really nicely. And it means that our note editor schema can be still used on the client and the server.
02:25 If we did want to split those things up and say, hey, we've got to validate it differently, then we definitely have ways to do that. You simply add a super refine or a refine to these different fields. And that is another way that you could approach this. But we're good with just going with file. Okay.
02:45 But we want to validate this file a little bit better. So we are, in fact, going to add a refine. And this, again, this is going to run both on the client and the server. And the refinement we want to make is that the file has the proper file size. So it can't be bigger than our max upload size of three megabytes.
03:01 The benefit of putting this validation logic right here is that it means that users who try to upload them will get that error message there as well, which is pretty darn handy, I should say. Okay. And with that, we can also add an error message that says file is too large.
03:19 So may as well explain. And typically, when you're doing a refine, you definitely want to provide an error message. And most of the time, you're going to want to provide error messages for these as well. But yeah, definitely for these refinements, because the error message itself is not going to be very useful otherwise. Okay, great.
03:37 So we've got our schema all set up. And so now we can come down here and get rid of all of this stuff. In fact, we'll get rid of all that. And now this can come right here, we have image ID file, and alt text.
03:56 And all of this is type safe and beautiful and amazing. And so we've got all of those properties there. And this needs to be ID, there we go. And it should all continue to work. So let's cross our fingers and hope that it does. Here we go.
04:13 Cuddling and submit, boom, look at that. Awesome. So well done you on this exercise of adding validation to file uploads. So to review this quickly, we've got image ID and alt text. That's just typical Zod schema stuff.
04:32 The file was a little bit interesting, because we have the fact that we want to validate this as a file on the client. We also want to validate this as a file on the server. And we can do that because it turns into a file object by the time it shows up in parse.
04:49 I think it might be instructive or helpful for you to visualize that if we add a console log of form data.get file. And now if I change the file right here, and then this is going to be a server side log. So it'll be over here, I hit submit. And we're going to see right there. This is a blob.
05:09 This is actually a file object, but it includes the size and the type and other information there. And you can dive into that a little bit deeper, again, going into the memory upload handler and seeing here it's creating this new file object. So that's why it's working.
05:25 I really like that Remix just embraces the web platform and uses these web standards, because it makes my life as a developer easier. So there you go, we validated our file with our Zod schema. And now everything is super duper type safe and all of that goodness as well. Super cool.