Java文件传输和上传

  • 用到的包:common-io、common-fileload

    文件上传调优(注意事项):

    • 为保证服务器安全,上传的文件应该放在外界无法直接访问的目录下,比如说WEB-INF目录下

    • 为防止文件覆盖的现象发生,要为上传的文件产生唯一的文件名

    • 要限制上传文件的最大值

    • 可以限制文件的类型,在收到文件名时,判断后缀名是否合法

    • ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象,在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象。所以我们需要在进行解析工作前构造好DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。

    流程

    • 页面必须包含一个type为file的表单

    method必须为post因为get限制了大小

    • ddfa.jsp
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
    <title>test</title>
    </head>
    <body>
    <form action="${pageContext.request.contextPath}/upload.do" method="post" enctype="multipart/form-data">
    <p>上传用户:<input type="text" name="username"></p>
    <p><input type="file" name="file"></p>
    <p>
    <input type="submit">|<input type="reset">
    </p>
    </form>
    </body>
    </html>
    • index.jsp(success.jsp)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
    <meta charset="utf-8">
    <title>FileUpload</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="/css/layui.css" tppabs="/css/layui.css" media="all">
    <!-- 注意:如果你直接复制所有代码到本地,上述css路径需要改成你本地的 -->


    </head>
    <body>
    <p>${msg}</p>


    <!-- 后续页面美化可以使用layui实现 -->
    <fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;">
    <legend>拖拽上传</legend>
    </fieldset>

    <div class="layui-upload-drag" id="test10">
    <i class="layui-icon"></i>
    <p>点击上传,或将文件拖拽到此处</p>
    <div class="layui-hide" id="uploadDemoView">
    <hr>
    <img src="" alt="上传成功后渲染" style="max-width: 196px">
    </div>
    </div>


    <script src="/js/layui.js" charset="utf-8"></script>
    <!-- 注意:如果你直接复制所有代码到本地,上述 JS 路径需要改成你本地的 -->
    <script>
    layui.use(['upload', 'element', 'layer'], function(){
    var $ = layui.jquery
    ,upload = layui.upload
    ,element = layui.element
    ,layer = layui.layer;


    //拖拽上传
    upload.render({
    elem: '#test10'
    ,url: '${pageContext.request.contextPath}/upload.do' //此处用的是第三方的 http 请求演示,实际使用时改成您自己的上传接口即可。
    ,done: function(res){
    layer.msg('上传成功');
    layui.$('#uploadDemoView').removeClass('layui-hide').find('img').attr('src', res.files.file);
    console.log(res)
    }
    });
    });
    </script>

    </body>
    </html>
    • FileUploadController:doPost
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 判断表单是否包含文件上传控件
    if (!ServletFileUpload.isMultipartContent(req)){
    // 不包含文件上传控件,即普通表单
    return;
    }

    //创建文件保存路径,外界无法访问
    String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
    File uploadFile = new File(uploadPath);
    makeIfNotExists(uploadFile);

    //创建临时文件保存路径
    String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
    File tmpFile = new File(tmpPath);
    makeIfNotExists(tmpFile);

    // 1.创建DiskFileItemFactory对象
    DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile);
    // 2.创建ServletFileUpload对象
    ServletFileUpload servletFileUpload = getServletFileUpload(factory);
    // 3.解析请求并处理文件传输
    String msg ="";
    try {
    msg = uploadParseRequest(req,servletFileUpload,uploadPath);
    } catch (FileUploadException e) {
    e.printStackTrace();
    }

    req.setAttribute("msg",msg);
    req.getRequestDispatcher("/index.jsp").forward(req,resp);
    }
    • getDiskFileItemFactory:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /**
    * 获得文件项目工程,设置缓冲文件夹以及缓冲区大小
    * @param tmpFile 缓冲文件夹
    * @return
    */
    private DiskFileItemFactory getDiskFileItemFactory(File tmpFile){
    DiskFileItemFactory factory = new DiskFileItemFactory();
    factory.setSizeThreshold(1024*1024);//超出缓冲区使用临时文件缓存上传
    factory.setRepository(tmpFile);//临时文件夹

    • getSercletFileUpload:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    private ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){
    ServletFileUpload servletFileUpload = new ServletFileUpload();
    servletFileUpload.setFileItemFactory(factory);

    // 辅助功能
    //监听文件上传进度
    servletFileUpload.setProgressListener(new ProgressListener() {
    @Override
    //已读文件大小 文件大小
    public void update(long pBytesRead, long pContentLength, int pItems) {
    String percentage = (int) (((double)pBytesRead / pContentLength) *100) +"%";
    System.out.println("总大小:"+pContentLength+",已上传:"+pBytesRead +"\t" + percentage);
    }
    });
    // 处理乱码问题
    servletFileUpload.setHeaderEncoding("UTF-8");
    // 设置单个文件的最大值
    servletFileUpload.setFileSizeMax(1024*1024*10);
    //设置总文件的最大值
    servletFileUpload.setSizeMax(1024*1024*50);

    return servletFileUpload;
    }
    • uploadParseRequest:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60

    private String uploadParseRequest(HttpServletRequest req,ServletFileUpload servletFileUpload,String uploadPath) throws FileUploadException, IOException {
    String msg = "" ;

    //解析前端请求 将每个表单项解析并封装成FileItem对象;
    List<FileItem> fileItems = servletFileUpload.parseRequest(req);
    for (FileItem fileItem : fileItems) {
    //判断表单项是否为上传文件
    if (fileItem.isFormField()){
    //普通文本
    String fieldName = fileItem.getFieldName();//获取字段名:表达name的属性的值
    String value = fileItem.getString("UTF-8");
    System.out.println(fieldName+":"+value);
    }else {
    // 上传文件
    // 1.处理文件
    String uploadFileName = fileItem.getName();//上传文件名
    System.out.println("the name of uploaded file:"+uploadFileName);

    if (uploadFileName == null || uploadFileName.trim().equals("")){
    continue;
    }
    String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".")+1);//文件后缀
    System.out.println("info about the file: [name:"+uploadFileName+" extname:"+fileExtName+"]");

    // use uuid make it unique
    String uuidPath = UUID.randomUUID().toString();

    // 2.处理路径
    // storePath: uploadpath 目录下的 唯一目录
    String realPath = uploadPath + "/" + uuidPath;
    File realPathFile = new File(realPath);
    makeIfNotExists(realPathFile);
    // 3.文件传输
    // get inputStream
    InputStream is = fileItem.getInputStream();
    // get outputStream write into a unique dir as a file
    OutputStream outputStream = new FileOutputStream(realPathFile+"/"+uploadFileName);

    //make cache
    byte[] buffer = new byte[1024];

    int len;
    while ((len = is.read(buffer))>0){
    outputStream.write(buffer,0,len);
    }


    msg = "文件上传成功";

    fileItem.delete();//上传成功,清除临时文件

    //close IOStream
    outputStream.close();
    is.close();
    }
    }

    return msg;
    }
    • makeIfNotExists:
    1
    2
    3
    4
    5
    private void makeIfNotExists(File file){
    if(!file.exists()){
    file.mkdir();
    }
    }
    • web.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <?xml version="1.0" encoding="UTF-8"?>
    <!--把这里的约束换成最新的-->
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
    http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    version="4.0">

    <servlet>
    <servlet-name>FileUpload</servlet-name>
    <servlet-class>xyz.yiochin.controller.FileController</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>FileUpload</servlet-name>
    <url-pattern>/upload.do</url-pattern>
    </servlet-mapping>

    <filter>
    <filter-name>characterEncoding</filter-name>
    <filter-class>xyz.yiochin.filter.EncodingFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>characterEncoding</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>

    <welcome-file-list>
    <welcome-file>/ddfa.jsp</welcome-file>
    </welcome-file-list>
    </web-app>

    作者: Meow Mii

    本文链接: https://blog.yiochin.top/p/48dafabf.html

    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议,转载请注明出处!


    📝 Comment