servlet文件上传blob_如何使用JSP / Servlet将文件上传到服务器?

介绍

要浏览并选择要上载的文件,您需要在表单中使用HTML 字段。如HTML规范中所述,您必须使用该POST方法,并且必须enctype将表单的属性设置为"multipart/form-data"。

提交此类表单后,请求正文中的二进制多部分表单数据的格式与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或更高版本时,请使用本机API

如果您至少使用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")@MultipartConfigpublic class UploadServlet extends HttpServlet {

// ...}

然后,实现doPost()如下:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

String description = request.getParameter("description"); // Retrieves

Part filePart = request.getPart("file"); // Retrieves

String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // MSIE fix.

InputStream fileContent = filePart.getInputStream();

// ... (do your job here)

}

请注意Path#getFileName()。这是获取文件名的MSIE修复。此浏览器错误地沿名称发送完整文件路径,而不是仅发送文件名。

如果您有多文件上传,请按以下方式收集它们(遗憾的是没有这样的方法request.getParts("file")):

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// ...

List fileParts = request.getParts().stream().filter(part -> "file".equals(part.getName())).collect(Collectors.toList()); // Retrieves

for (Part filePart : fileParts) {

String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // MSIE fix.

InputStream fileContent = filePart.getInputStream();

// ... (do your job here)

}

}

如果您还没有使用Servlet 3.1,请手动获取提交的文件名

请注意,这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;

}

String fileName = getSubmittedFileName(filePart);

请注意MSIE修复以获取文件名。此浏览器错误地沿名称发送完整文件路径,而不是仅发送文件名。

如果您还没有使用Servlet 3.0,请使用Apache Commons FileUpload

如果您还没有使用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 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将获得一个空的请求体。另请参见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();

}

String description = getValue(request.getPart("description")); // Retrieves

保存上传的文件(不要使用getRealPath()也不part.write()!)

有关将获得的InputStream(fileContent上面的代码片段中显示的变量)正确保存到磁盘或数据库的详细信息,请转到以下答案:

提供上传的文件

有关将已保存的文件从磁盘或数据库正确提供回客户端的详细信息,请转到以下答案:

Ajax化表单

转到以下答案如何使用Ajax(和jQuery)上传。请注意,收集表单数据的servlet代码不需要为此更改!只有您的响应方式可能会被更改,但这是相当简单的(即,不是转发到JSP,只是打印一些JSON或XML甚至纯文本,具体取决于负责Ajax调用的脚本所期望的)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值