Tha*_*ham 671 java jsp servlets file-upload java-ee
如何使用JSP/Servlet将文件上传到服务器?我试过这个:
<form action="upload" method="post">
<input type="text" name="description" />
<input type="file" name="file" />
<input type="submit" />
</form>
Run Code Online (Sandbox Code Playgroud)
但是,我只获取文件名,而不是文件内容.当我添加 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.
Run Code Online (Sandbox Code Playgroud)
不幸的是,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)
Run Code Online (Sandbox Code Playgroud)
Bal*_*usC 1161
要浏览并选择要上载的文件,您需要<input type="file">在表单中使用HTML 字段.如HTML规范中所述,您必须使用该POST方法,并且必须enctype将表单的属性设置为"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>
Run Code Online (Sandbox Code Playgroud)
提交此类表单后,请求正文中的二进制多部分表单数据的格式与enctype未设置时的格式不同.
在Servlet 3.0之前,Servlet API本身不支持multipart/form-data.它仅支持默认的表单enctype application/x-www-form-urlencoded.在request.getParameter()和配偶都会返回null使用多形式的数据时.这是众所周知的Apache Commons FileUpload进入图片的地方.
理论上,您可以基于自己解析请求体ServletRequest#getInputStream().但是,这是一项精确而繁琐的工作,需要精确了解RFC2388.你不应该试图自己动手做,或者在互联网上的其他地方找到一些本土的无库代码.许多在线消息来源都很难,例如roseindia.net.另见pdf文件的上传.您应该使用数百万用户多年使用(并隐式测试!)的真实库.这样的库已经证明了它的稳健性.
如果您至少使用Servlet 3.0(Tomcat 7,Jetty 9,JBoss AS 6,GlassFish 3等),那么您可以使用提供的标准API HttpServletRequest#getPart()来收集单个多部分表单数据项(大多数Servlet 3.0实现实际上使用Apache Commons FileUpload为此提供了保障!).此外,通常的方式可以使用普通表单字段getParameter().
首先注释你的servlet,@MultipartConfig以便让它识别和支持multipart/form-data请求,从而开始getPart()工作:
@WebServlet("/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet {
// ...
}
Run Code Online (Sandbox Code Playgroud)
然后,实现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)
}
Run Code Online (Sandbox Code Playgroud)
请注意Path#getFileName().这是获取文件名的MSIE修复.此浏览器错误地沿名称发送完整文件路径,而不是仅发送文件名.
如果您<input type="file" name="file" multiple="true" />有多文件上传,请按以下方式收集它们(遗憾的是没有这样的方法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">
for (Part filePart : fileParts) {
String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
InputStream fileContent = filePart.getInputStream();
// ... (do your job here)
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这Part#getSubmittedFileName()是在Servlet 3.1(Tomcat 8,Jetty 9,WildFly 8,GlassFish 4等)中引入的.如果您还没有使用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;
}
Run Code Online (Sandbox Code Playgroud)
String fileName = getSubmittedFileName(filePart);
Run Code Online (Sandbox Code Playgroud)
请注意MSIE修复以获取文件名.此浏览器错误地沿名称发送完整文件路径,而不是仅发送文件名.
如果您还没有使用Servlet 3.0(现在不是升级时间吗?),通常的做法是使用Apache Commons FileUpload来解析多部分表单数据请求.它有一个优秀的用户指南和常见问题解答(仔细阅读两者).还有O'Reilly(" cos ")MultipartRequest,但它有一些(小的)错误,并且多年来不再积极维护.我不建议使用它.Apache Commons FileUpload仍然在积极维护,目前非常成熟.
要使用Apache Commons FileUpload,您需要在webapp中至少包含以下文件/WEB-INF/lib:
您最初的尝试失败的可能性很大,因为您忘记了公共IO.
以下是使用Apache Commons FileUpload时doPost()您的UploadServlet样子的启动示例:
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);
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
这是非常重要的,你不叫getParameter(),getParameterMap(),getParameterValues(),getInputStream(),getReader(),等上了同样的要求提前.否则,servlet容器将读取并解析请求体,因此Apache Commons FileUpload将获得一个空的请求体.另请参见ao ServletFileUpload #parseRequest(request)返回一个空列表.
请注意FilenameUtils#getName().这是获取文件名的MSIE修复.此浏览器错误地沿名称发送完整文件路径,而不是仅发送文件名.
或者,您也可以将其全部包装在一个Filter自动解析所有内容中并将这些内容放回请求的参数图中,以便您可以继续使用request.getParameter()常规方法并检索上传的文件request.getAttribute().您可以在此博客文章中找到一个示例.
getParameter()仍然返回的GlassFish3错误的解决方法null需要注意的是Glassfish的版本早于3.1.2有一个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();
}
Run Code Online (Sandbox Code Playgroud)
String description = getValue(request.getPart("description")); // Retrieves <input type="text" name="description">
Run Code Online (Sandbox Code Playgroud)
getRealPath()也不part.write()!)有关将获得的InputStream(fileContent上面的代码片段中显示的变量)正确保存到磁盘或数据库的详细信息,请转到以下答案:
有关将已保存的文件从磁盘或数据库正确提供回客户端的详细信息,请转到以下答案:
转到以下答案如何使用Ajax(和jQuery)上传.请注意,收集表单数据的servlet代码不需要为此更改!只有您的响应方式可能会被更改,但这是相当简单的(即,不是转发到JSP,只是打印一些JSON或XML甚至纯文本,具体取决于负责Ajax调用的脚本所期望的).
希望这一切都有帮助:)
Ami*_*ila 25
如果您碰巧使用Spring MVC,这是如何:(我将此留在这里以防有人发现它有用).
使用enctype属性设置为" multipart/form-data" 的表单(与BalusC的答案相同)
<form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value="Upload"/>
</form>
Run Code Online (Sandbox Code Playgroud)
在您的控制器中,将请求参数映射file到MultipartFiletype,如下所示:
@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
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用MultipartFile's getOriginalFilename()和' 获取文件名和大小getSize().
我用Spring版本测试了这个4.1.1.RELEASE.
我正在为每个 Html表单使用公共Servlet,无论它是否有附件.此Servlet返回一个TreeMap键,其中键是jsp名称参数和值是用户输入并将所有附件保存在固定目录中,稍后您重命名所选目录.Here Connections是具有连接对象的自定义接口.我想这会对你有所帮助
public class ServletCommonfunctions extends HttpServlet implements
Connections {
private static final long serialVersionUID = 1L;
public ServletCommonfunctions() {}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {}
public SortedMap<String, String> savefilesindirectory(
HttpServletRequest request, HttpServletResponse response)
throws IOException {
// Map<String, String> key_values = Collections.synchronizedMap( new
// TreeMap<String, String>());
SortedMap<String, String> key_values = new TreeMap<String, String>();
String dist = null, fact = null;
PrintWriter out = response.getWriter();
File file;
String filePath = "E:\\FSPATH1\\2KL06CS048\\";
System.out.println("Directory Created ????????????"
+ new File(filePath).mkdir());
int maxFileSize = 5000 * 1024;
int maxMemSize = 5000 * 1024;
// Verify the content type
String contentType = request.getContentType();
if ((contentType.indexOf("multipart/form-data") >= 0)) {
DiskFileItemFactory factory = new DiskFileItemFactory();
// maximum size that will be stored in memory
factory.setSizeThreshold(maxMemSize);
// Location to save data that is larger than maxMemSize.
factory.setRepository(new File(filePath));
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// maximum file size to be uploaded.
upload.setSizeMax(maxFileSize);
try {
// Parse the request to get file items.
@SuppressWarnings("unchecked")
List<FileItem> fileItems = upload.parseRequest(request);
// Process the uploaded file items
Iterator<FileItem> i = fileItems.iterator();
while (i.hasNext()) {
FileItem fi = (FileItem) i.next();
if (!fi.isFormField()) {
// Get the uploaded file parameters
String fileName = fi.getName();
// Write the file
if (fileName.lastIndexOf("\\") >= 0) {
file = new File(filePath
+ fileName.substring(fileName
.lastIndexOf("\\")));
} else {
file = new File(filePath
+ fileName.substring(fileName
.lastIndexOf("\\") + 1));
}
fi.write(file);
} else {
key_values.put(fi.getFieldName(), fi.getString());
}
}
} catch (Exception ex) {
System.out.println(ex);
}
}
return key_values;
}
}
Run Code Online (Sandbox Code Playgroud)
Tomcat 6 o 7中没有组件或外部库
在web.xml文件中启用上载:
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<multipart-config>
<max-file-size>3145728</max-file-size>
<max-request-size>5242880</max-request-size>
</multipart-config>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
Run Code Online (Sandbox Code Playgroud)
你可以看到:
<multipart-config>
<max-file-size>3145728</max-file-size>
<max-request-size>5242880</max-request-size>
</multipart-config>
Run Code Online (Sandbox Code Playgroud)
使用JSP上传文件.文件:
在html文件中
<form method="post" enctype="multipart/form-data" name="Form" >
<input type="file" name="fFoto" id="fFoto" value="" /></td>
<input type="file" name="fResumen" id="fResumen" value=""/>
Run Code Online (Sandbox Code Playgroud)
在JSP文件或Servlet中
InputStream isFoto = request.getPart("fFoto").getInputStream();
InputStream isResu = request.getPart("fResumen").getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte buf[] = new byte[8192];
int qt = 0;
while ((qt = isResu.read(buf)) != -1) {
baos.write(buf, 0, qt);
}
String sResumen = baos.toString();
Run Code Online (Sandbox Code Playgroud)
编辑代码到servlet要求,例如max-file-size,max-request-size 和你可以设置的其他选项......
小智 8
对于Spring MVC, 我已经尝试了几个小时来做这个并且设法有一个更简单的版本,用于表单输入数据和图像.
<form action="/handleform" method="post" enctype="multipart/form-data">
<input type="text" name="name" />
<input type="text" name="age" />
<input type="file" name="file" />
<input type="submit" />
</form>
Run Code Online (Sandbox Code Playgroud)
控制器处理
@Controller
public class FormController {
@RequestMapping(value="/handleform",method= RequestMethod.POST)
ModelAndView register(@RequestParam String name, @RequestParam int age, @RequestParam MultipartFile file)
throws ServletException, IOException {
System.out.println(name);
System.out.println(age);
if(!file.isEmpty()){
byte[] bytes = file.getBytes();
String filename = file.getOriginalFilename();
BufferedOutputStream stream =new BufferedOutputStream(new FileOutputStream(new File("D:/" + filename)));
stream.write(bytes);
stream.flush();
stream.close();
}
return new ModelAndView("index");
}
}
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你 :)
小智 6
如果您使用Geronimo及其嵌入式Tomcat,则会出现此问题的另一个原因.在这种情况下,在测试commons-io和commons-fileupload的多次迭代之后,问题来自处理commons-xxx jar的父类加载器.必须防止这种情况.崩溃总是发生在:
fileItems = uploader.parseRequest(request);
Run Code Online (Sandbox Code Playgroud)
请注意,fileItems的List类型已更改为当前版本的commons-fileupload,List<FileItem>而不是通用版本的先前版本List.
我将commons-fileupload和commons-io的源代码添加到我的Eclipse项目中以跟踪实际错误并最终得到一些见解.首先,抛出的异常是Throwable类型,而不是声明的FileIOException,甚至Exception(这些都不会被捕获).其次,错误消息是混淆的,因为它声明找不到类,因为axis2找不到commons-io.Axis2根本不在我的项目中使用,但作为标准安装的一部分存在于Geronimo存储库子目录中的文件夹中.
最后,我找到了一个提出成功解决问题的工作解决方案的地方.您必须在部署计划中隐藏来自父加载程序的jar.这被放入geronimo-web.xml,我的完整文件如下所示.
Pasted from <http://osdir.com/ml/user-geronimo-apache/2011-03/msg00026.html>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<web:web-app xmlns:app="http://geronimo.apache.org/xml/ns/j2ee/application-2.0" xmlns:client="http://geronimo.apache.org/xml/ns/j2ee/application-client-2.0" xmlns:conn="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2" xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2" xmlns:ejb="http://openejb.apache.org/xml/ns/openejb-jar-2.2" xmlns:log="http://geronimo.apache.org/xml/ns/loginconfig-2.0" xmlns:name="http://geronimo.apache.org/xml/ns/naming-1.2" xmlns:pers="http://java.sun.com/xml/ns/persistence" xmlns:pkgen="http://openejb.apache.org/xml/ns/pkgen-2.1" xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0" xmlns:web="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1">
<dep:environment>
<dep:moduleId>
<dep:groupId>DataStar</dep:groupId>
<dep:artifactId>DataStar</dep:artifactId>
<dep:version>1.0</dep:version>
<dep:type>car</dep:type>
</dep:moduleId>
<!--Don't load commons-io or fileupload from parent classloaders-->
<dep:hidden-classes>
<dep:filter>org.apache.commons.io</dep:filter>
<dep:filter>org.apache.commons.fileupload</dep:filter>
</dep:hidden-classes>
<dep:inverse-classloading/>
</dep:environment>
<web:context-root>/DataStar</web:context-root>
</web:web-app>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
538774 次 |
| 最近记录: |