hi i'm cameron mckenzie @cameronmcnz on twitter and I wanted to talk to you about doing some
file uploads specifically doing some file uploads with Java. I'm just going to show you how to put
together a nice little servlet that's got that multi-part config annotation on it and it can
use any ajax based or form-based html file that wants to upload a file or a resource to the server
so kicking off this java servlet ajax file upload project i need a web project it's going
to be maven based here i like maven i'm going to choose to create a maven project just a simple one
and for the group id i'll make it com.mcnz.web the artifact is going to be servlet java web ajax
upload i guess and then the package which is the only thing that really matters here is going to be
war because this is a web module now as soon as i fill this out eclipse is going to clap back at me
saying hey you know what this is a web module and you're supposed to have a web.xml file in it you
can see that white x right there some people say it's a red x it is not a red x it has a white x
on a red background but it says web.xml is missing and so i can fix that i've actually got to make a
couple of changes to this palm file here i have to add one dependency and a couple of plug-in
references so i'm going to throw this code in here and just explain it in a moment what i'm doing is
i'm saying that in order for this to run i need the servlet api 4.01 and in fact you need 3.1 or
newer the stuff i'm going to do here won't work on 2.5 if you're using 2.5 upgrade to 3.1 or 4. for
that matter on 2.5 you'd have to use the apache commons.io file uploader to get this to work
if you're using 3.0 most of this will work except getting the file name with the parts object
so that would be frustrating if you're using 3.1 or newer everything will work i'm using 4 so life
is good so that's the one dependency i need on the servlet and jsp api the other thing i need to set
notice here i've got the maven war plug-in and i'm telling it to not bother me about that
web.xml file fail on missingweb.xml false so that should get rid of my error and i'm also using the
maven compiler plugin to force jdk and java 1.8 compliance so that is the maven palm file feel
free to use gradin gradle feel free to just drop different files into the folder there i'm going
to go maven update project but maven tends to be a pretty good way to manage your dependencies okay
now that's just the basic configuration i want to do a file upload and if i want to do a file
upload i need a file uploader that means creating an html file which i'm going to call uploader.html
and then this html file along with all the basic html that eclipse will give me java ajax
servlet file upload just put a title in there if you want
what really matters is what goes in here and what goes in here is my form element that includes
a file selector so i'm going to start off by putting a form element in here method is post
it's going to call a server that i will create in a moment called the file upload servlet
and the encoding type is going to be multi-part basically when the server when the browser
sends data to the server it chunks it it doesn't send a great big 10 gig file it
sends it you know one mag at a time or whatever it sends it in parts and so the file upload type is
multi-part and when we configure our servlet we're going to have to make sure that it supports that
with an annotation but that's important i'm going to end my form there now when
you create an html form with html5 you can use the html5 type file element notice this type
equals file that's new before you only had submit or you only had input or text area
so we can actually have a file input when this runs this will actually display a selector field
where somebody can click on a button and browse their local file system for a file so that's new
that's our html5 element we also need a submit button to send this to the server and so this is
the client part of the application now if you really want to be tricky and i don't know if
i like hanging around people that are tricky but one of the things you can do is you can actually
you can actually do an ajax call so you can add in let me see if i can do this here how do i do this
you can add in you don't have to use a form you can just add in an input field and a button
and the input field again file type so that's going to be the
selector and we can have a button that calls on a javascript method
and we can have this uploaded through javascript the javascript if you're a ajax javascript person
i was born in ajax ontario so i guess i'm an ajax person the script isn't too difficult
the script isn't too difficult but i did paste it in incorrectly there so it would help if i
did it properly okay here's the script it's right there okay here's what the script does
the script runs when somebody clicks on this button upload file calls the upload file method
this method creates a form data object which it's going to use to send data to the server what it
wants to send to the server is this file here right it's got the id of ajax file so we can say
get the file associated with that ajax file name it file and put it into the form that's
the file name that's the name file there that's going to go in the request response parameter
headers so we put that send that up to the server with the name file we call the file upload servlet
with a post including that form data and then hopefully everything goes well on the server
when the server says yeah that all works we get an alert on the client so the cool thing about this
is this is going to upload the files using ajax you won't leave the page whereas with the form
you will anyways a little razzle dazzle there just giving you an idea of how you can actually
implement that both using a standard static form and also using some super cool ajax now
none of this is going to work unless we've got a component on the server which
captures this incoming request if you think putting together a little form is all you
need in order to get a file uploader working you've got another thing coming i've got to
come over to the server here and i've got to create a new servlet this servlet is going to
be the com.mcnc.web package and it's going to be called the file upload servlet i'll click
next there i don't want like that mapping i think all servlet should be file upload servlet i think
all servlets and web resources should be all lower case letters so i'm changing that there
i don't want any of this stuff and just click click finish and that gives me my nice little
class right there file upload extends http servlet i'm actually going to update that web servlet
mapping there probably don't need to but i'm going to change this i'm just going to add a name and
url pattern there i think that just looks a little bit more explicit although i don't think i needed
to do that but what i do need to do is i need to add this annotation here and notice as soon
as i add this annotation it's going to clap back at me right there that's only because i need to
organize my import so that the code can actually find that class as it's imported there you'll see
imported multi-part config but what this does is it makes it possible for this servlet to be able
to handle file uploads in chunked format so that upload.html file it sent data in multi-parts here
we are going to do a multi-part config annotation to allow support for that okay and this file
uploader it used the post invocation so did ajax it used post as well that means over on the server
i have to implement a do post method so i'm going to put that in there that's just your standard do
post method nothing crazy or interesting about that again i have to organize my imports because
i can't find the servlet request and serve the response object but no problem now what do i
actually do in this code well we're going to have all sorts of parts of files coming to the server
so what i'm going to do is i'm actually just going to get one of those parts i can say hey
just give me one of those parts and from the parts that are coming to the server i want the
name of the file that was uploaded i'm going to use the name of the file as it was uploaded
as the name of the file that i save on the file system i mean i could you know every
time a file comes in i could call it abc123.jpg or something but it makes sense if somebody
uploads a file named kaliselfie.jpg i save it locally as kali selfie.jpg
that will give me the file name now by the way i believe this won't work on 3.0 just definitely
won't work on 2.5 none of this will work in 2.5 but 3.0 you have to take a different strategy for
getting the file name so you are forewarned looks like i need to do an organize import once again
and there we go the little error message on file part went away okay so now what do i want to do
well i want to save all of that file all of the chunks into my upload folder and so i'm going to
loop through all of the different chunks that are sent up here so get all the parts from the request
object and one part at a time what i want to do is i want to write that data into a file in c
upload right now there's nothing in that c upload folder you can see that right there nothing in it
and the file that i want to write to is basically the file that's got the same name as the file that
was uploaded so i take the file name of the upload and i create a file in this folder and then i
write all the pieces to it essentially taking the file that was uploaded and saving it to the local
machine now finally this is a servlet so i could forward to a jsp i'm just going to write something
out and say hey the file was uploaded successfully way to go um you know i mean this isn't uh
you know great mvc and maybe uh it's not going to be win me any awards for ui development but
it's going to work and working is good i'll allow you to deal with corner cases
and fixing uh and writing any unit tests on your own i just want to get this to work but that's
it one two three four five lines of code how could life get any easier that's all you have to do with
server 3.1 to handle file upload and save that file locally now i'm just going to look at my code
did i do everything right here there's the input buttons there's the form file upload servlet okay
this all looks good the ajax call with the post okay well i am going to deploy this i'm going to
take a look at that uploader.html right click say run as run on server we need a tomcat 9 server in
order to run this but i will run it and i will click finish i'm actually going to take that
url right there and i'm actually going to just paste it into chrome so there's chrome right
there running that program so that looks good i'm also going to bring the upload folder over here as
well as you can see there's nothing currently in it and then i'm going to choose a file so there's
cali looking happy nice smile she's always taking selfies so i got the cali selfie i'll upload it
and bang there we go that file is uploaded to that folder now that was a full request response
cycle change the page but if i come over here and do ajax i can choose a file and there is a
nice little picture of my book i can open that file up click upload here it says the file was
uploaded with ajax and java successfully and now that pickering springfield book is right there and
so now i've got this working both with a standard form and with ajax and there you go that's all
there is to putting together a java based file upload with servlet and jsp api 3.1 using html
form and input elements and making it all standard static or even asynchronous and ajax based
and there you go that's how easy it is to do file uploads with java whether you want to use a basic
form or even add some ajax and javascript in there now if you enjoyed that tutorial head
over to theserverside.com i'm the editor-in-chief over there we've got lots of great tutorials on
enterprise software development with java java ee jakarta devops you name it if you're interested
in my personal antics you can always follow me on twitter cameronmcnz and subscribe on youtube