javaweb 文件上传 commons-fileupload

13 篇文章 0 订阅
5 篇文章 0 订阅

文件上传
一、表单页面限制
1、method=”post”
2、enctype=”multipart/form-data”
3、表单中添加
二、服务端限制
request.getParametere(“xxx”);这个方法在表单为enctype=”multipart/form-data”时,它作废了,永远返回null
ServletInputStream request.getInputStream(); 包含整个请求体

服务端解析数据:
为了简化开发,使用commons-fileupload框架解析数据
commons-fileupload开发
一、创建工厂
二、创建解析器
三、获取表单每项数据

1、上传文件保存路径必须是WEB-INF目录,一般在WEB-INF目录下建个files用于存放
2、上传文件名称为绝对路径时,进行转换拿到文件名
    int index = fileName.lastIndexOf("\\");
    if (index != -1) {
        fileName = fileName.substring(index + 1);
    }
3、文件名称乱码,在所有的操作前设置request.setCharacterEncoding("UTF-8");
4、文件名同名问题
    public static String getUUID() {
        return UUID.randomUUID().toString().replace("-", "").toUpperCase();
    }
    fileName = CommonUtils.getUUID() + "_" + fileName;
5、上传目录打散(哈希打散)
//目录打散
    int hCode = fileName.hashCode();// 得到哈希整型
    String hex = Integer.toHexString(hCode);// 转成十六进制
    // 获取十六进制前2位
    String realPath = this.getServletContext().getRealPath("/WEB-INF/files");
    File dir = new File(realPath, hex.charAt(0) + File.separator + hex.charAt(1));
    dir.mkdirs();
    File desFile = new File(dir, fileName);

    //\WEB-INF\files\a\b\686E7ACDC900406A83679BC25BD2930A_ab.png
6、上传文件的大小限制
    fileUpload.setSizeMax(fileSizeMax);设置上传文件大小4M
    fileUpload.setFileSizeMax(sizeMax);设置请求总文件大小4M
    以上设置在tomcat7.0.39没问题,但是在其他后续版本的tomcat版本就出问题了,也不知道是那个问题
    所以没办法用以上办法来限制用户的上传
    为了解决,我尝试了一个方法,就是自己来判断文件的大小,超出限制了就抛出同样的异常就可以了,
    同样我们捕获异常提醒用户上传的文件大了
7、上传之缓存大小与临时目录
    // 创建DiskFileItemFactory工厂,构造函数可以直接设置缓冲区和目录,也可以调用方法来设置
        //创建是直接设置
        DiskFileItemFactory factory = new DiskFileItemFactory(2 * 1024, new File("D:\\temp"));
        //创建好再调用方法设置
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setSizeThreshold(2 * 1024);// 设置缓冲区大小,这里是2kb
        factory.setRepository(new File("D:\\temp"));// 设置缓冲临时目录

代码:web

${msg }
    <h1>上传</h1>
    <form action="${pageContext.request.contextPath }/FileServlet" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="username"><br/>
    照   片:<input type="file" name="zhaoPian"><br/>
    照   片:<input type="file" name="zhaoPian1"><br/>
    照   片:<input type="file" name="zhaoPian2"><br/>
    <input type="submit"  value="上传">

服务器端代码:

request.setCharacterEncoding("UTF-8");
        // 检测request中是否包含有multipart内容,就是文件上传的意思
        if (ServletFileUpload.isMultipartContent(request)) {
            try {
                // 创建DiskFileItemFactory工厂,构造函数可以直接设置缓冲区和目录,也可以调用方法来设置
                DiskFileItemFactory factory = new DiskFileItemFactory(2 * 1024, new File("D:\\temp"));
                factory.setSizeThreshold(2 * 1024);// 设置缓冲区大小,这里是2kb
                factory.setRepository(new File("D:\\temp"));// 设置缓冲临时目录

                // 创建上传ServletFileUpload类,并将DiskFileFactory工厂传给它
                ServletFileUpload fileUpload = new ServletFileUpload(factory);
                // 设置编码,防止中文乱码
                fileUpload.setHeaderEncoding("UTF-8");

                // 定义好文件大小的限制和总大小的限制
                long fileSizeMax = 4 * 1024 * 1024;
                long sizeMax = 10 * 1024 * 1024;

                // fileUpload.setSizeMax(fileSizeMax);设置上传文件大小4M
                // fileUpload.setFileSizeMax(sizeMax);设置请求总文件大小4M

                // 从request得到上传的文件列表
                List<FileItem> list = fileUpload.parseRequest(request);

                // 由于使用setSizeMax方法和setFileSizeMax方法设置限制上传文件大小会出现问题,所以自己写判断了,还是用抛出异常FileSizeLimitExceededException
                // 这个for循环是为了校验文件大小限制的
                long sizeCount = 0;
                for (FileItem fileItem : list) {
                    long fileSize = fileItem.getSize();
                    sizeCount += fileSize;
                    if (!fileItem.isFormField() && fileSize > fileSizeMax) {
                        throw new FileSizeLimitExceededException(
                                fileItem.getName() + "文件大小" + fileSize + " ,超出了限制" + fileSizeMax, fileSize,
                                fileSizeMax);
                    }
                    if (sizeCount > sizeMax) {
                        throw new SizeLimitExceededException("文件总大小" + sizeCount + " ,超出了限制" + sizeCount, sizeCount,
                                sizeMax);
                    }

                }

                // 这个for循环是开始解析保存数据
                for (FileItem fileItem : list) {
                    // FileItem fileItem = list.get(1);
                    if (fileItem.isFormField()) {// 判断是否是文件field,当是表单域时,进行的处理
                        String fieldName = fileItem.getFieldName();// 得到元素的name属性的值
                        String fieldValue = fileItem.getString("utf-8");// 得到元素的value的值
                        String fileName = fileItem.getName();// 这里是表单域,所以得到的是null
                        System.out.println(
                                "fieldName:" + fieldName + "  fieldValue:" + fieldValue + "  fileName:" + fileName);
                    } else {// 当是文件域时,将文件保存到硬盘中
                        String fileName = fileItem.getName();// 得到文件名
                        // 判断文件名是否是空的,空的就是没有文件数据,不用处理,跳过本条目
                        if (fileName == null || fileName.trim().isEmpty()) {
                            continue;
                        }
                        // 提取文件名,防止有的浏览器是全路径,如eclipse自带浏览器就是C:\Users\HC\Downloads\88107.rar
                        int index = fileName.lastIndexOf("\\");
                        if (index != -1) {
                            fileName = fileName.substring(index + 1);
                        }
                        // 根据文件名获取哈希值,转成十六进制,为目录打散做准备
                        int hCode = fileName.hashCode();
                        String hex = Integer.toHexString(hCode);

                        // 为了防止文件重名,加入uuid_前缀
                        fileName = UUID.randomUUID().toString().replace("-", "").toUpperCase() + "_" + fileName;
                        // 得到服务器保存路径
                        String savePath = this.getServletContext().getRealPath("/WEB-INF/files");
                        // 目录打散,加入哈希十六进制前2位,一位一目录名,上下关系,目录打散是为了打开没那么卡,所以文件都放同一个文件夹肯定卡的
                        File dir = new File(savePath, hex.charAt(0) + File.separator + hex.charAt(1));
                        dir.mkdirs();// 如果目录不存在就自动创建,存在就什么都不做

                        System.out.println(dir.getAbsolutePath());
                        // 得到最终的包含文件名的文件路径
                        File desFile = new File(dir, fileName);
                        // 创建输出流,用于保存文件
                        FileOutputStream fos = new FileOutputStream(desFile);

                        IOUtils.copy(fileItem.getInputStream(), fos);

                        fos.close();

                    }
                }
                request.setAttribute("msg", "上传成功");
                request.getRequestDispatcher("/form2.jsp").forward(request, response);
            } catch (FileSizeLimitExceededException e) {
                // response.sendRedirect(this.getServletContext().getContextPath()+"/form1.jsp");
                request.setAttribute("msg", e.getMessage());
                request.getRequestDispatcher("/form2.jsp").forward(request, response);
                e.printStackTrace();
            } catch (SizeLimitExceededException e) {
                request.setAttribute("msg", e.getMessage());
                request.getRequestDispatcher("/form2.jsp").forward(request, response);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

文件上传限制问题解决方法参考:https://blog.csdn.net/adsl624153/article/details/72803626
https://blog.csdn.net/w47_csdn/article/details/76422357

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值