java - How to upload files to server using JSP/Servlet? -


how can upload files server using jsp/servlet? tried this:

<form action="upload" method="post">     <input type="text" name="description" />     <input type="file" name="file" />     <input type="submit" /> </form> 

however, file name, not file content. when add enctype="multipart/form-data" <form>, request.getparameter() returns null.

during research stumbled upon apache common fileupload. tried this:

fileitemfactory factory = new diskfileitemfactory(); servletfileupload upload = new servletfileupload(factory); list items = upload.parserequest(request); // line died. 

unfortunately, servlet threw exception without clear message , cause. here stacktrace:

severe: servlet.service() servlet uploadservlet threw exception javax.servlet.servletexception: servlet execution threw exception     @ org.apache.catalina.core.applicationfilterchain.internaldofilter(applicationfilterchain.java:313)     @ org.apache.catalina.core.applicationfilterchain.dofilter(applicationfilterchain.java:206)     @ org.apache.catalina.core.standardwrappervalve.invoke(standardwrappervalve.java:233)     @ org.apache.catalina.core.standardcontextvalve.invoke(standardcontextvalve.java:191)     @ org.apache.catalina.core.standardhostvalve.invoke(standardhostvalve.java:127)     @ org.apache.catalina.valves.errorreportvalve.invoke(errorreportvalve.java:102)     @ org.apache.catalina.core.standardenginevalve.invoke(standardenginevalve.java:109)     @ org.apache.catalina.connector.coyoteadapter.service(coyoteadapter.java:298)     @ org.apache.coyote.http11.http11processor.process(http11processor.java:852)     @ org.apache.coyote.http11.http11protocol$http11connectionhandler.process(http11protocol.java:588)     @ org.apache.tomcat.util.net.jioendpoint$worker.run(jioendpoint.java:489)     @ java.lang.thread.run(thread.java:637) 

introduction

to browse , select file upload need html <input type="file"> field in form. stated in html specification have use post method , enctype attribute of form has set "multipart/form-data".

<form action="upload" method="post" enctype="multipart/form-data">     <input type="text" name="description" />     <input type="file" name="file" />     <input type="submit" /> </form> 

after submitting such form, binary multipart form data available in request body in a different format when enctype isn't set.

before servlet 3.0, servlet api didn't natively support multipart/form-data. supports default form enctype of application/x-www-form-urlencoded. request.getparameter() , consorts return null when using multipart form data. known apache commons fileupload came picture.

don't manually parse it!

you can in theory parse request body based on servletrequest#getinputstream(). however, precise , tedious work requires precise knowledge of rfc2388. shouldn't try on own or copypaste homegrown library-less code found elsewhere on internet. many online sources have failed hard in this, such roseindia.net. see uploading of pdf file. should rather use real library used (and implicitly tested!) millions of users years. such library has proven robustness.

when you're on servlet 3.0 or newer, use native api

if you're using @ least servlet 3.0 (tomcat 7, jetty 9, jboss 6, glassfish 3, etc), can use standard api provided httpservletrequest#getpart() collect individual multipart form data items (most servlet 3.0 implementations use apache commons fileupload under covers this!). also, normal form fields available getparameter() usual way.

first annotate servlet @multipartconfig in order let recognize , support multipart/form-data requests , getpart() work:

@webservlet("/upload") @multipartconfig public class uploadservlet extends httpservlet {     // ... } 

then, implement dopost() follows:

protected void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {     string description = request.getparameter("description"); // retrieves <input type="text" name="description">     part filepart = request.getpart("file"); // retrieves <input type="file" name="file">     string filename = paths.get(filepart.getsubmittedfilename()).getfilename().tostring(); // msie fix.     inputstream filecontent = filepart.getinputstream();     // ... (do job here) } 

note path#getfilename(). msie fix obtaining file name. browser incorrectly sends full file path along name instead of file name.

in case have <input type="file" name="file" multiple="true" /> multi-file upload, collect them below (unfortunately there no such method request.getparts("file")):

protected void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {     // ...     list<part> fileparts = request.getparts().stream().filter(part -> "file".equals(part.getname())).collect(collectors.tolist()); // retrieves <input type="file" name="file" multiple="true">      (part filepart : fileparts) {         string filename = paths.get(filepart.getsubmittedfilename()).getfilename().tostring(); // msie fix.         inputstream filecontent = filepart.getinputstream();         // ... (do job here)     } } 

when you're not on servlet 3.1 yet, manually submitted file name

note part#getsubmittedfilename() introduced in servlet 3.1 (tomcat 8, jetty 9, wildfly 8, glassfish 4, etc). if you're not on servlet 3.1 yet, need additional utility method obtain submitted file name.

private static string getsubmittedfilename(part part) {     (string cd : part.getheader("content-disposition").split(";")) {         if (cd.trim().startswith("filename")) {             string filename = cd.substring(cd.indexof('=') + 1).trim().replace("\"", "");             return filename.substring(filename.lastindexof('/') + 1).substring(filename.lastindexof('\\') + 1); // msie fix.         }     }     return null; } 
string filename = getsubmittedfilename(filepart); 

note msie fix obtaining file name. browser incorrectly sends full file path along name instead of file name.

when you're not on servlet 3.0 yet, use apache commons fileupload

if you're not on servlet 3.0 yet (isn't time upgrade?), common practice make use of apache commons fileupload parse multpart form data requests. has excellent user guide , faq (carefully go through both). there's o'reilly ("cos") multipartrequest, has (minor) bugs , isn't actively maintained anymore years. wouldn't recommend using it. apache commons fileupload still actively maintained , mature.

in order use apache commons fileupload, need have @ least following files in webapp's /web-inf/lib:

your initial attempt failed because forgot commons io.

here's kickoff example how dopost() of uploadservlet may when using apache commons fileupload:

protected void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {     try {         list<fileitem> items = new servletfileupload(new diskfileitemfactory()).parserequest(request);         (fileitem item : items) {             if (item.isformfield()) {                 // process regular form field (input type="text|radio|checkbox|etc", select, etc).                 string fieldname = item.getfieldname();                 string fieldvalue = item.getstring();                 // ... (do job here)             } else {                 // process form file field (input type="file").                 string fieldname = item.getfieldname();                 string filename = filenameutils.getname(item.getname());                 inputstream filecontent = item.getinputstream();                 // ... (do job here)             }         }     } catch (fileuploadexception e) {         throw new servletexception("cannot parse multipart request.", e);     }      // ... } 

it's important don't call getparameter(), getparametermap(), getparametervalues(), getinputstream(), getreader(), etc on same request beforehand. otherwise servlet container read , parse request body , apache commons fileupload empty request body. see a.o. servletfileupload#parserequest(request) returns empty list.

note filenameutils#getname(). msie fix obtaining file name. browser incorrectly sends full file path along name instead of file name.

alternatively can wrap in filter parses automagically , put stuff in parametermap of request can continue using request.getparameter() usual way , retrieve uploaded file request.getattribute(). you can find example in blog article.

workaround glassfish3 bug of getparameter() still returning null

note glassfish versions older 3.1.2 had a bug wherein getparameter() still returns null. if targeting such container , can't upgrade it, need extract value getpart() of utility method:

private static string getvalue(part part) throws ioexception {     bufferedreader reader = new bufferedreader(new inputstreamreader(part.getinputstream(), "utf-8"));     stringbuilder value = new stringbuilder();     char[] buffer = new char[1024];     (int length = 0; (length = reader.read(buffer)) > 0;) {         value.append(buffer, 0, length);     }     return value.tostring(); } 
string description = getvalue(request.getpart("description")); // retrieves <input type="text" name="description"> 

saving uploaded file (don't use getrealpath() nor part.write()!)

head following answers detail on saving obtained inputstream (the filecontent variable shown in above code snippets) disk or database:

serving uploaded file

head following answers detail on serving saved file disk or database client:

ajaxifying form

head following answers how upload using ajax (and jquery). note servlet code collect form data not need changed this! way how respond may changed, rather trivial (i.e. instead of forwarding jsp, print json or xml or plain text depending on whatever script responsible ajax call expecting).


hope helps :)


Comments

Popular posts from this blog

javascript - Using jquery append to add option values into a select element not working -

Android soft keyboard reverts to default keyboard on orientation change -

Rendering JButton to get the JCheckBox behavior in a JTable by using images does not update my table -