如何使用JSP / Servlet将文件上传到服务器?我试过这个:
<form action="upload" method="post">
<input type="text" name="description" />
<input type="file" name="file" />
<input type="submit" />
</form>
但是,我只获取文件名,而不是文件内容 . 当我将 enctype="multipart/form-data"
添加到 <form>
时, request.getParameter()
返回 null
.
在研究期间,我偶然发现了Apache Common FileUpload . 我试过这个:
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List items = upload.parseRequest(request); // This line is where it died.
不幸的是,servlet抛出异常而没有明确的消息和原因 . 这是堆栈跟踪:
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)
12 回答
简介
要浏览并选择要上载的文件,您需要在表单中使用HTML
<input type="file">
字段 . 如HTML specification中所述,您必须使用POST
方法,并且表单的enctype
属性必须设置为"multipart/form-data"
.提交此类表单后,二进制多部分表单数据在a different format中的请求正文中可用,而不是在未设置
enctype
时 .在Servlet 3.0之前,Servlet API本身不支持
multipart/form-data
. 它仅支持application/x-www-form-urlencoded
的默认表单enctype . 使用多部分表单数据时,request.getParameter()
和consorts都将返回null
. 这是众所周知的Apache Commons FileUpload进入画面的地方 .不要手动解析它!
理论上,您可以根据ServletRequest#getInputStream()自己解析请求体 . 然而,这是一项精确而繁琐的工作,需要精确的RFC2388知识 . 你不应该试图自己做这个或者复制一些在互联网上其他地方找到的本土的无库代码 . 许多在线消息来源都很难,例如roseindia.net . 另见uploading of pdf file . 您应该使用数百万用户多年使用(并隐式测试!)的真实库 . 这样的库已经证明了它的稳健性 .
当您已经使用Servlet 3.0或更高版本时,请使用本机API
如果您至少使用Servlet 3.0(Tomcat 7,Jetty 9,JBoss AS 6,GlassFish 3等),那么您可以使用提供的标准API HttpServletRequest#getPart()来收集单个多部分表单数据项(大多数Servlet 3.0实现实际使用) Apache Commons FileUpload为此提供了支持!) . 此外,通常的方式可以通过
getParameter()
获得普通表单字段 .首先使用@MultipartConfig注释您的servlet,以便让它识别并支持
multipart/form-data
请求,从而使getPart()
工作:然后,按如下方式实现
doPost()
:注意
Path#getFileName()
. 这是获取文件名的MSIE修复 . 此浏览器错误地沿名称发送完整文件路径,而不是仅发送文件名 .如果您有多个文件上传的
<input type="file" name="file" multiple="true" />
,请按以下方式收集它们(遗憾的是,没有request.getParts("file")
这样的方法):当你还没有使用Servlet 3.1时,手动获取提交的文件名
请注意,Part#getSubmittedFileName()是在Servlet 3.1(Tomcat 8,Jetty 9,WildFly 8,GlassFish 4等)中引入的 . 如果您还没有使用Servlet 3.1,那么您需要一个额外的实用工具方法来获取提交的文件名 .
请注意MSIE修复以获取文件名 . 此浏览器错误地沿名称发送完整文件路径,而不是仅发送文件名 .
当您还没有使用Servlet 3.0时,请使用Apache Commons FileUpload
如果您有时间升级?),通常的做法是使用Apache Commons FileUpload来解析多部分表单数据请求 . 它有一个优秀的User Guide和FAQ(仔细检查两者) . 有's also the O' Reilly(“cos”)
MultipartRequest
,但它有一些(小的)错误,并且不推荐使用它 . Apache Commons FileUpload仍在积极维护,目前非常成熟 .要使用Apache Commons FileUpload,您需要在webapp的
/WEB-INF/lib
中至少包含以下文件:commons-fileupload.jar
commons-io.jar
您最初的尝试失败的可能性很大,因为您忘记了公共IO .
以下是使用Apache Commons FileUpload时
UploadServlet
的doPost()
如何显示的启动示例:它's very important that you don' t事先在同一请求上调用
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 .GlassFish3的解决方法getParameter()的bug仍然返回null
请注意,早于3.1.2的Glassfish版本具有a bug,其中
getParameter()
仍然返回null
. 如果您要定位此类容器但无法升级它,则需要在此实用程序的帮助下从getPart()
中提取值方法:保存上传的文件(不要使用getRealPath()或part.write()!)
有关将获得的
InputStream
(如上面的代码片段中所示的fileContent
变量)正确保存到磁盘或数据库的详细信息,请转到以下答案:Recommended way to save uploaded files in a servlet application
How to upload an image and save it in database?
How to convert Part to Blob, so I can store it in MySQL?
提供上传的文件
有关将已保存的文件从磁盘或数据库正确提供回客户端的详细信息,请转到以下答案:
Load images from outside of webapps / webcontext / deploy folder using <h:graphicImage> or <img> tag
How to retrieve and display images from a database in a JSP page?
Simplest way to serve static data from outside the application server in a Java web application
Abstract template for static resource servlet supporting HTTP caching
Ajaxifying表单
转到以下答案如何使用Ajax(和jQuery)上传 . 请注意,收集表单数据的servlet代码不需要为此更改!只有你的响应方式可能会被改变,但这是微不足道的(即,不是转发到JSP,只是打印一些JSON或XML甚至纯文本,具体取决于负责Ajax调用的脚本所期望的) .
How to upload files to server using JSP/Servlet and Ajax?
sending a file as multipart through xmlHttpRequest
HTML5 File Upload to Java Servlet
希望这一切都有帮助:)
Without component or external Library in Tomcat 6 o 7
在 web.xml 文件中启用上载:
http://joseluisbz.wordpress.com/2014/01/17/manually-installing-php-tomcat-and-httpd-lounge/#Enabling%20File%20Uploads .
如你看到的:
Uploading Files using JSP. Files:
在html文件中
在JSP文件或Servlet中
将代码编辑为servlet要求,例如max-file-size,max-request-size和其他可以设置的选项...
如果您碰巧使用Spring MVC,这是如何:(我将离开这里以防有人发现它有用) .
使用
enctype
属性设置为“multipart/form-data
”的表单(与BalusC的答案相同)在控制器中,将请求参数
file
映射到MultipartFile
类型,如下所示:您可以使用
MultipartFile
的getOriginalFilename()
和getSize()
获取文件名和大小 .我用Spring版
4.1.1.RELEASE
测试了这个 .这是使用apache commons-fileupload的示例:
HTML PAGE
SERVLET文件
web.xml中
编译上面的servlet UploadServlet并在web.xml文件中创建所需的条目,如下所示 .
你可以使用jsp / servlet上传文件 .
另一方面服务器端 . 使用以下代码 .
如果您使用Geronimo及其嵌入式Tomcat,则会出现此问题的另一个原因 . 在这种情况下,在测试commons-io和commons-fileupload的多次迭代之后,问题出现在处理commons-xxx jar的父类加载器上 . 必须防止这种情况 . 崩溃总是发生在:
请注意,fileItems的List类型已更改,当前版本的commons-fileupload具体为
List<FileItem>
,而不是之前的版本List
.我将commons-fileupload和commons-io的源代码添加到我的Eclipse项目中以跟踪实际错误并最终得到一些见解 . 首先,抛出的异常是Throwable类型,而不是声明的FileIOException,甚至Exception(这些都不会被捕获) . 其次,错误消息是混淆的,因为它声明找不到类,因为axis2找不到commons-io . Axis2根本不在我的项目中使用,但作为标准安装的一部分存在于Geronimo存储库子目录中的文件夹中 .
最后,我找到了一个提出成功解决问题的工作解决方案的地方 . 您必须在部署计划中隐藏来自父加载程序的jar . 这被放入geronimo-web.xml,我的完整文件如下所示 .
发送文件的多个文件我们必须使用
enctype="multipart/form-data"
并在输入标签中发送多个文件
multiple="multiple"
您需要将
common-io.1.4.jar
文件包含在lib
目录中,或者如果您在任何编辑器(如NetBeans)中工作,那么您需要转到项目属性并添加JAR文件,您将完成 .要获取
common.io.jar
文件只是google它或只是去Apache Tomcat网站,您可以在其中获得免费下载此文件的选项 . 但请记住一件事:如果您是Windows用户,请下载二进制ZIP文件 .我正在使用 every Html表单的公共Servlet是否有附件 . 此Servlet返回
TreeMap
,其中键是jsp名称参数和值是用户输入并将所有附件保存在固定目录中,稍后您重命名所选目录.Here Connections是具有连接对象的自定义接口 . 我想这会对你有所帮助For Spring MVC 我已经尝试了几个小时来做这个并且设法有一个更简单的版本,用于表单输入数据和图像 .
控制器处理
希望能帮助到你 :)
从这个对象你必须得到文件项和字段,然后你可以存储到服务器,如下所示: