php editor Youzi will introduce to you how to use JSP/Servlet to upload files to the server in Java. In Web development, file upload is a common requirement, and JSP/Servlet can be used to implement a simple and efficient file upload function. Next, we will introduce in detail how to upload files to the server through Java code, so that you can quickly master this skill and improve your development capabilities.
How to use jsp/servlet to upload files to the server?
I tried this:
<form action="upload" method="post"> <input type="text" name="description" /> <input type="file" name="file" /> <input type="submit" /> </form>
However, I only get the file name, not the file content. When I add enctype="multipart/form-data"
to <form>
, request.getparameter()
returns null
.
During my research, I stumbled upon apache common fileupload. I tried this:
fileitemfactory factory = new diskfileitemfactory(); servletfileupload upload = new servletfileupload(factory); list items = upload.parserequest(request); // this line is where it died.
Unfortunately, the servlet threw an exception, but there is no clear message and reason. Here is the stack trace:
SEVERE: Servlet.service() for servlet UploadServlet threw exception javax.servlet.ServletException: Servlet execution threw an exception at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:313) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) at java.lang.Thread.run(Thread.java:637)
To browse and select a file to upload, you need to add an html <input type="file">
field to your form. As stated in the HTML specification, you must use the post
method, and the form's enctype
attribute must be set to "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 such a form is submitted, binary multipart form data is available in the request body in a different format
than when enctype is not set.
Prior to servlet 3.0 (December 2009), the servlet api itself did not support multipart/form-data
. It only supports the default form enctype application/x-www-form-urlencoded
. When using multipart form data, both request.getparameter()
and consorts will return null
. This is where the well-known Apache Commons FileUpload comes in.
Theoretically you can parse the request body yourself according to ServletRequest#getInputStream()
. However, this is a precise and tedious task that requires precise knowledge of RFC2388. You shouldn't try to do this yourself or copy-paste some homemade libraryless code found elsewhere on the internet. Many online resources fail in this regard, such as roseindia.net. See also uploading of pdf file. You should use a real library that has been used (and implicitly tested!) by millions of users for years. Such a library has proven its robustness.
If you are using at least servlet 3.0 (tomcat 7, jetty 9, jboss as 6, glassfish 3, etc., they have been around since 2010) then you can use HttpServletRequest#getPart()
Provides a standard API to collect individual multi-part form data items (most servlet 3.0 implementations actually use apache commons fileupload behind the scenes!). Additionally, normal form fields can be obtained in the usual way via getparameter()
.
First annotate your servlet with @MultipartConfig
so that it recognizes and supports multipart/form-data
requests, allowing getpart( )
normal work:
@webservlet("/upload") @multipartconfig public class uploadservlet extends httpservlet { // ... }
Then, implement it as follows dopost()
:
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 your job here) }
Note path#getfilename()
. This is an msie fix regarding getting filenames. This browser incorrectly sends the full file path and name instead of just the file name.
If you want to upload multiple files via multiple="true"
,
<input type="file" name="files" multiple="true" />
Or the old fashioned way with multiple inputs,
<input type="file" name="files" /> <input type="file" name="files" /> <input type="file" name="files" /> ...
Then you can collect them as follows (unfortunately there is no method like request.getparts("files")
):
protected void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { // ... list<part> fileparts = request.getparts().stream().filter(part -> "files".equals(part.getname()) && part.getsize() > 0).collect(collectors.tolist()); // retrieves <input type="file" name="files" multiple="true"> for (part filepart : fileparts) { string filename = paths.get(filepart.getsubmittedfilename()).getfilename().tostring(); // msie fix. inputstream filecontent = filepart.getinputstream(); // ... (do your job here) } }
请注意,Part#getSubmittedFileName()
是在 servlet 3.1 中引入的(tomcat 8、jetty 9、wildfly 8、glassfish 4 等,它们自 2013 年以来就已存在)。如果您还没有使用 servlet 3.1(真的吗?),那么您需要一个额外的实用方法来获取提交的文件名。
private static string getsubmittedfilename(part part) { for (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);
请注意有关获取文件名的 msie 修复。此浏览器错误地发送完整文件路径和名称,而不仅仅是文件名。
如果您还没有使用 servlet 3.0(是不是该升级了?它已经十多年前发布了!),通常的做法是使用 Apache Commons FileUpload 来解析多部分表单数据请求。它有一个很好的User Guide和FAQ(仔细检查两者)。还有 o'reilly(“cos”)multipartrequest
,但它有一些(小)错误,并且多年来不再积极维护。我不建议使用它。 apache commons fileupload 仍在积极维护,目前非常成熟。
为了使用 apache commons fileupload,您的 web 应用程序的 /web-inf/lib
中至少需要有以下文件:
您最初的尝试失败很可能是因为您忘记了公共 io。
下面是一个启动示例,显示使用 apache commons fileupload 时 uploadservlet
的 dopost()
的样子:
protected void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { try { list<fileitem> items = new servletfileupload(new diskfileitemfactory()).parserequest(request); for (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 your 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 your job here) } } } catch (fileuploadexception e) { throw new servletexception("cannot parse multipart request.", e); } // ... }
非常重要的是,您不要事先在同一请求上调用 getparameter()
、getparametermap()
、getparametervalues()
、getinputstream()
、getreader()
等。否则,servlet 容器将读取并解析请求正文,因此 apache commons fileupload 将得到一个空请求正文。另请参见 a.o. ServletFileUpload#parseRequest(request) returns an empty list。
注意 filenameutils#getname()
。这是有关获取文件名的 msie 修复。此浏览器错误地发送完整文件路径和名称,而不仅仅是文件名。
或者,您也可以将这一切包装在 filter
中,它会自动解析所有内容并将内容放回请求的参数映射中,以便您可以继续以通常的方式使用 request.getparameter()
并通过以下方式检索上传的文件request.getattribute()
。 You can find an example in this blog article。
getparameter()
错误的解决方法仍然返回 null
请注意,早于 3.1.2 的 glassfish 版本有 a bug,其中 getparameter()
仍返回 null
。如果您的目标是这样的容器并且无法升级它,那么您需要借助此实用程序方法从 getpart()
中提取值:
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]; for (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">
getrealpath()
或 part.write()
!)前往以下答案,详细了解如何将获得的 inputstream
(上述代码片段中所示的 filecontent
变量)正确保存到磁盘或数据库:
请参阅以下答案,了解如何正确地将保存的文件从磁盘或数据库返回给客户端的详细信息:
前往以下答案,了解如何使用 ajax(和 jquery)上传。请注意,无需为此更改用于收集表单数据的 servlet 代码!只有您响应的方式可能会改变,但这相当简单(即,不转发到 jsp,只需打印一些 json 或 xml 甚至纯文本,具体取决于负责 ajax 调用的脚本所期望的内容)。
如果您碰巧使用 Spring MVC,请按以下方法操作(我将其留在这里,以防有人发现它有用):
使用 enctype
属性设置为“multipart/form-datazqbenczqb”的表单(与 <a href="https://www.php.cn/link/8a13dab3f5ec9e22d0d1495c8c85e436">BalusC's answer</a> 相同):</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:html;toolbar:false;"><form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value="upload"/>
</form>
</pre><div class="contentsignin">Copy after login</div></div>
<p>在您的控制器中,将请求参数 <code>file
映射到 multipartfile
类型,如下所示:
@RequestMapping(value = "/upload", method = RequestMethod.POST) public void handleUpload(@RequestParam("file") MultipartFile file) throws IOException { if (!file.isEmpty()) { byte[] bytes = file.getBytes(); // alternatively, file.getInputStream(); // application logic } }
您可以使用 multipartfile
的 getoriginalfilename()
和 getsize()
获取文件名和大小。
我已经使用 spring 版本 4.1.1.release
对此进行了测试。
The above is the detailed content of How to upload files to server using JSP/Servlet?. For more information, please follow other related articles on the PHP Chinese website!