Servlet3.0的MultipartConfig注解来进行上传文件

我们可以知道在servlet3.0前上传文件是利用fileupload组件来上传,而3.0新增的multipartconfig注解简化了上传文件的复杂度。

一、客户端编程

  要上传文件,必须利用multipart/form-data设置HTML表单的enctype属性值:

    <form action="servlet/FileServlet" enctype="multipart/form-data" method="post">
        <input type="file" name="uploadFile" multiple/> <!--multiple为H5的可以添加多个文件的属性,如果只能上传一个,去掉即可-->
        <input type="text" name="tag" />
        <input type="submit" value="Upload"/>
    </form>

二、服务器端编程(servlet编写)

  1. MultipartConfig注解与http.part接口的使用

  (1) MultipartConfig可以带有以下属性,都为可选的:

  maxFileSize:表示最多可以上传的文件的容量,超过设定值的文件将会遭到拒绝,默认值为-1,表示无限制。

  maxRequestSize:表示允许多部分HTTP请求的最大容量,默认值为-1,意味着它是不受限制的。

  location:将上传的文件保存在服务器中项目的指定位置,调用Part的write方法会使用,但是,只有write中填写为相对路径,那么意味着是相对于location的路径,如果是填写为绝对路径,则与location无关。

  fileSizeThreshold:设定溢出大小,超过这个值那么上传的文件就会被写入磁盘

  (2) http.part接口:

  在一个有多部分请求组成的请求中,每一个表单域,包括非文件域,都会被转换成一个个Part。

  HttpServletRequest接口定义了以下方法来获取Part:

  Part getPart(String name)  返回与指定名称相关的Part,名称为相关表单域的名称(name)

扫描二维码关注公众号,回复: 1538995 查看本文章

  Colleciton<Part> getParts()  返回这个请求中的所有Part

  Part接口中定义的方法:

  String getName()  获取这部分的名称,例如相关表单域的名称

  String getContentType()  如果Part是一个文件,那么将返回Part的内容类型,否则返回null(可以利用这一方法来识别是否为文件域)

  Collection<String> getHeaderNames()  返回这个Part中所有标头的名称

  String getHeader(String headerName)  返回指定标头名称的值

  void write(String path)  将上传的文件写入服务器中项目的指定地址下,如果path是一个绝对路径,那么将写入指定的路径,如果path是一个相对路径,那么将被写入相对于location属性值的指定路径。

  InputStream getInputStream()  以inputstream的形式返回上传文件的内容

  

  2. 说明

  如果HTML的输入是一个文件域,那么Part将返回这些标头:

  content-type:contentType

  content-disposition:form-data; name="filedName"; filename="fileName"

  如果是一个普通文本域,那么:

  content-disposition:form-data; name="filedName"

  如果是文件域,但没有上传文件,那么:

  content-type:application/octet-stream

  content-disposition:form-data; name="filedName"; filename=""

  

  3. 实例

@WebServlet(name = "FileServlet", urlPatterns = "/servlet/FileServlet")
@MultipartConfig()
public class FileServlet extends HttpServlet {

    private String getFileName(Part part) {
        String contentDisposition = part.getHeader("content-disposition");
        String[] elements = contentDisposition.split(";");
        for (String element : elements) {
            if (element.trim().startsWith("filename")) {
                return element.substring(element.indexOf('=') + 1).trim().replace("\"", "");
            }
        }
        return null;
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Part part = request.getPart("uploadFile");  //提取文件域的part
        //System.out.println(request.getContextPath());
        //System.out.println(request.getServletPath());
        //System.out.println(request.getRequestURI());       
//System.out.println(getServletContext().getRealPath("/upload"));
        String fileName = getFileName(part);
        if (fileName != null && !fileName.isEmpty()) {
            part.write(getServletContext().getRealPath("/upload") + "/" + fileName);    //服务器中项目目录下的upload目录,绝对路径
        }
    }

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

    }
}
 

  多文件上传,只需在以上基础上,加一个遍历part,一个个分析即可。

三、第一次编写遇到的问题:

  在Part的write方法上碰到了瓶颈,第一次我使用的是part.write(request.getContextPath() + "/upload/" + fileName),发现出现错误:

  发现write的路径却是拼接了 request.getContextPath() + "/upload/" + fileName 路径。在路径跳转中如果路径开头有一个/,那么代表是绝对路径,而request.ContextPath()返回开头有斜杆,而write却将其作为相对路径,由此可以推测出,write只识别路径字符串,并不会像路径跳转那样识别斜杆,识别../这些。

  

  然后我使用了 part.write(getServletContext().getRealPath("/upload") + "/" + fileName) ,毫无疑问这返回是项目在服务器中的绝对路径,但是却又出现错误:

  发现保存路径是在IDEA的项目空间下,又想起IDEA在部署项目到tomcat的时候并不是直接部署,即你在tocmat的webapps下找不到部署的项目,详情见:http://www.cnblogs.com/chenloveslife/p/8727646.html。

  

  由于出错是部署的项目(不是原工作空间的项目)中没有upload文件夹,然后我在IDEA的我的项目下的out的war_explode新增了upload文件夹(如果在工作空间的项目根下创建upload文件夹,并且该文件夹中有任意文件,那么在redeploy后,它也会部署到war_exploded,就无需直接在war_exploded中创建文件夹了),war_explode代表在tomcat中的项目,运行项目,路径正确并成功上传。

  以上为基础的上传文件,有时还需要处理如果出现同名的文件应该如何处理,以及处理多个上传文件,以及控制上传文件大小,优化等等。

  

猜你喜欢

转载自www.cnblogs.com/chenloveslife/p/9159049.html
今日推荐