JavaEE 使用Servlet上传文件

    xiaoxiao2021-03-26  34

    Servlet3.0提供了javax.servlet.http.Part类,通过它可以很方便的上传文件。

    Part类介绍

    javax.servlet.http.Part是Servlet3.0中新增加的API之一。每个Part对象表示一个文件上传域,该对象提供了许多方法来获得上传文件的类型、大小、输入流等,还提供了一个write方法将文件写入服务器磁盘。

    Part类的常用方法有: - getHeaderNames:获得用户请求头中的MIME值名称; - getContentType:获得上传文件的类型; - getSize:获得上传文件的大小; - getSubmittedFileName:获得上传文件在客户端的绝对路径; - write:将上传文件写入服务器磁盘。

    使用Servlet上传文件

    Servlet

    先来看我们的程序,首先是处理文件上传的Servlet类:

    // UploadServlet.java @WebServlet( urlPatterns = { "/upload" }, initParams = { @WebInitParam(name = "basepath", value = "F:\\workspace\\javaEE\\WebDemo\\res\\") }, asyncSupported = true) @MultipartConfig public class UploadServlet extends HttpServlet { private String basePath; private static final long serialVersionUID = 1L; public void init(ServletConfig config) throws ServletException { basePath=config.getInitParameter("basepath"); } protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { AsyncContext ac=request.startAsync(request, response); ac.setTimeout(10*60*1000); ac.addListener(new AsyncListener() { @Override public void onComplete(AsyncEvent event) throws IOException { AsyncContext ac=event.getAsyncContext(); ac.getResponse().getWriter().println("文件上传成功!<br>"); ac.dispatch("/upload"); } @Override public void onError(AsyncEvent event) throws IOException { event.getAsyncContext().getResponse().getWriter().println("文件上传出错!<br>"); } @Override public void onStartAsync(AsyncEvent event) throws IOException { event.getAsyncContext().getResponse().getWriter().println("开始上传文件...<br>"); } @Override public void onTimeout(AsyncEvent event) throws IOException { event.getAsyncContext().getResponse().getWriter().println("文件上传超时!<br>"); } }); ac.start(new UploadTask(ac, basePath)); } public static class UploadTask implements Runnable { private AsyncContext ac; private String basePath; public UploadTask(AsyncContext a, String bp) { ac=a; basePath=bp; } @Override public void run() { HttpServletRequest request=(HttpServletRequest) ac.getRequest(); HttpServletResponse response=(HttpServletResponse) ac.getResponse(); response.setContentType("text/html;charset=GBK"); PrintWriter out; try { out = response.getWriter(); Part part=request.getPart("file"); // 文件上传头 Collection<String> headers=part.getHeaderNames(); // 文件类型 String fileType=part.getContentType(); // 文件大小 long fileSize=part.getSize(); // 客户端上传的文件名 String submitName=part.getSubmittedFileName(); // 服务器保存的文件名 String fileName=UUID.randomUUID().toString()+ submitName.substring(submitName.lastIndexOf('.')); out.println("HEADER: "+"<br>"); for(String header : headers) out.println(header+"="+part.getHeader(header)+"<br>"); out.println("文件类型: "+fileType+"<br>"); out.println("文件大小: "+fileSize+"<br>"); out.println("客户端文件名: "+submitName+"<br>"); out.println("服务端文件名: "+fileName+"<br>"); if(fileType.startsWith("image")) part.write(basePath+"image\\"+fileName); else if(fileType.startsWith("audio")) part.write(basePath+"audio\\"+fileName); else if(fileType.startsWith("video")) part.write(basePath+"video\\"+fileName); else part.write(basePath+"file\\"+fileName); ac.complete(); } catch (IOException e) { e.printStackTrace(); } catch (ServletException e) { e.printStackTrace(); } } } }

    由于上传文件是一个耗时的工作,所以我们使用异步处理来上传文件,关于异步处理的内容可以参考我的另一篇文章:《JavaEE Servlet的异步处理》。

    在UploadTask中进行实际的文件上传工作。request.getPart方法可以获得文件上传域对象,我们通过调用它的一系列方法输出了文件信息,最后调用write方法将其写入磁盘。

    另外还要注意,如果想要上传文件,Servlet需要使用@MultipartConfig注解配置。

    jsp页面

    下面还需要一个jsp页面来选择要上传的文件:

    <!-- upload.jsp --> <body> <form method="post" action="upload" enctype="multipart/form-data"> 选择文件: <input type="file" id="file" name="file"><br> <input type="submit" value="上传"><br> </form> </body>

    form表单中有几个需要注意的地方: 1. 多了一个enctype属性,它指定表单数据的编码方式,该属性有如下三个值: - application/x-www-form-urlencoded:这是默认的方式,此方式只会发送文件域的文本框中的字符串,即用户选择文件的绝对路径; - multipart/form-data:此方式以二进制流处理表单数据,这种方式会发送文件域指定文件的内容; - text/plain:此方式当表单的action属性为mailto:URL时比较方便,主要适用于直接通过表单发送邮件的方式。 2. 有一个类型为file的input,它就是文件上传域,它用于选择要上传的文件。

    上传文件

    现在我们开始上传文件,运行Web应用,选择upload.jsp页面,如下所示:

    然后我们随便选择一个文件,点击上传,结果如下(如果文件较大,可能需要等待较长的时间):

    可以看到,这里上传的文件在客户端和服务端具有不同的名字。这是因为如果有多位用户上传文件,他们上传的文件难免会有相同的文件名,所以我们使用java.util.UUID类来产生新的文件名。

    UUID(Universally Unique Identifier)全局唯一标识符,是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。按照开放软件基金会(OSF)制定的标准计算方法,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字。由以下几部分组合而成:当前日期和时间(UUID的第一个部分与时间有关,如果你在生成一个UUID之后,经过几秒又生成一个UUID,则第一个部分不同,其余相同),时钟序列,全局唯一的IEEE机器识别号(如果有网卡,从网卡获得,没有网卡则以其他方式获得),UUID的唯一缺陷在于生成的结果串会比较长。

    源码

    上述源代码已经上传到github: https://github.com/jzyhywxz/WebDemo

    转载请注明原文地址: https://ju.6miu.com/read-662048.html

    最新回复(0)