文件上传-java web

第一步:需要引入两个依赖:common-fileupload和commin-io.

第二步.在web页面中添加上传文件的输入项

1.必须使用<input type="file">,设置input的name属性.

    <input type="file" name="file">

2.form表单的enctype必须设置为multipart/form-data.

    enctype="multipart/form-data"

3.form表单的提交方式必须是post.

    method="post"

第三步.编写servlet,将用户上传的数据保存到本地硬盘.

1.判断用户提交的是否是带文件的表单,如果是普通的表单中止方法运行,直接返回.

    if(!ServletFileUpload.isMultipartContent(request)){
        return;
    }

2.创建两个路径,一个文件保存的路径,一个是文件保存的临时路径,防止文件过大占用硬盘空间.

    String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
    File uploadFile = new File(uploadPath);
    if (!uploadFile.exists()){
        uploadFile.mkdirs();
    }

    String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
    File file = new File(tmpPath);
    if (!file.exists()){
        file.mkdirs();
    }

3.创建一个DiskFileItempFactory对象,相当于是一个缓冲区,将过大的文件放入临时路径.(将这个过程封装成方法一,参数是:临时路径,返回DiskFileItempFactory对象)

    DiskFileItemFactory factory = getDiskFileItemFactory(file);

4.创建并配置一个ServletFileUpload对象,需要用它来解析前端请求.(将这个过程封装成方法二,参数是:DiskFileItempFactory对象,返回值:ServletFileUpload对象)

    ServletFileUpload upload = getServletFileUpload(factory);

5.通过ServletFileUpload对象,将前端请求封装成FileItem对象,FileItem对象可以获取一个输入流,将这个流输出到本地磁盘上,就是用户上传的文件(将这个过程封装成方法三,参数是:ServletFileUpload对象,前端请求,文件保存路径,返回值:执行结果)

    String message = uploadParseRequest(upload, request, uploadPath);

6.根据执行结果对前端进行反馈,并跳转页面.

    if (Objects.equals(message, "文件上传成功!")){
        }else {
            message = "请上传文件!";
        }
        request.setAttribute("message",message);
        request.getRequestDispatcher("info.jsp").forward(request,response);

方法一

    /**
     * 上传文件的缓冲区
     * @param file 临时文件路径
     * @return DiskFileItemFactory对象
     */
    public static DiskFileItemFactory getDiskFileItemFactory(File file) {
        //创建一个DiskFileItemFactory对象
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //设置缓冲区大小为1M
        factory.setSizeThreshold(1024 * 1024);
        //设置临时文件的保存路径为方法参数中file
        factory.setRepository(file);
        //返回设置好的DiskFileItemFactory对象
        return factory;
    }

方法二

    /**
     * 对创建的ServletFileUpload对象进行配置
     * @param factory 缓存区
     * @return 配置好的ServletFileUpload对象
     */
    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
        //创建ServletFileUpload对象,传入设置好的缓存区对象
        ServletFileUpload upload = new ServletFileUpload(factory);
        // 监听上传进度
        upload.setProgressListener(new ProgressListener() {
            public void update(long pBytesRead, long pContentLength, int pItems) {
                System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead+",进度:"+((double)pBytesRead/pContentLength)*100+"%");
            }
        });
        // 处理编码,防止乱码
        upload.setHeaderEncoding("UTF-8");
        // 设置单个文件的最大值
        upload.setFileSizeMax(1024 * 1024 * 10);
        //返回ServletFileUpload对象
        return upload;
    }

方法三(核心方法)

    /**
     * 将前端请求中的文件写入本地磁盘
     * @param upload ServletFileUpload对象
     * @param request 前端请求
     * @param uploadPath 本地保存文件的路径
     * @return 执行结果
     * @throws FileUploadException 文件上传异常
     * @throws IOException IO异常
     */
    public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request, String uploadPath) throws FileUploadException, IOException {
        //创建返回结果
        String message = "";
        //利用ServletFileUpload对象将前端请求解析并封装成FileItem对象,返回一个FileItem对象集
        List<FileItem> fileItems = upload.parseRequest(request);
        //遍历封装后的FileItem对象
        for (FileItem fileItem : fileItems) {
            //判断前端提交的表单有没有文件上传
            if (fileItem.isFormField()) { //没有文件上传
                //getFieldName获取的的是前端表单控件的name;
                String name = fileItem.getFieldName();
                //处理乱码
                String value = fileItem.getString("UTF-8");
                System.out.println(name + ": " + value);
            } else {// 有文件上传

                // ============处理文件名开始==============

                // 拿到文件名
                String uploadFileName = fileItem.getName();
                System.out.println("上传的文件名: " + uploadFileName);
                //将文件名前后空格去除后,判断是否为空字符串
                if (uploadFileName.trim().equals("")) {
                    continue;
                }
                // 获取上传的文件名,将路径去除,只留下 / 后的字符串就是文件自己的名字 例如: C:\Users\lvjianhua\1.jpg
                String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
                // 获得文件的后缀名,将最后一个点后面的字符串获取,来判断文件类型 例如: C:\Users\lvjianhua\1.jpg
                String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
                //如果文件后缀名fileExtName不是我们所需要的 就直按return.不处理,告诉用户文件类型不对。
                System.out.println("文件信息[件名: " + fileName + " ---文件类型" + fileExtName + "]");

                // ================处理文件名完毕==============

                // ==============处理存放地址开始==============

                // 可以使用UID(唯一识别的通用码),保证文件名唯一
                // UUID.randomUUID(),这个方法可以随机生一个唯一识别的通用码;
                String uuidPath = UUID.randomUUID().toString();
                //用刚才随机生成的UUID和文件保存的路径拼接一个新路径,这个路径就是文件最后存储的路径
                String realPath = uploadPath + "/" + uuidPath;
                //根据这个新路径创建文件夹,每个文件都会有一个单独的文件夹,防止文件重名,发生覆盖,
                File realPathFile = new File(realPath);
                //判断文件夹是否存在
                if (!realPathFile.exists()) {
                    //不存在就生成一个
                    realPathFile.mkdir();
                }

                // ==============存放地址完毕==============

                // =============文件传输开始=============

                //通过FileItem对象获得文件上传的输入流
                InputStream is = fileItem.getInputStream();
                //创建输入流,文件路径就是,最终存放地址 + 文件名
                FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
                //创建一个缓冲区
                byte[] buffer = new byte[1024 * 1024];
                //设置一个int值,来储存读取数据的长度
                int len = 0;
                // 一边读,一边写,如果读取的数据长度大于0说明还存在数据,就继续输出
                while ((len = is.read(buffer)) > 0) {
                    fos.write(buffer, 0, len);
                }
                // 关闭流
                fos.close();
                is.close();
                //执行到此处,说明文件储存成功,给返回结果赋值
                message = "文件上传成功!";
                //上传成功,清除临时文件
                fileItem.delete();

                //=============文件传输完毕=============

            }
        }
        //返回执行结果
        return message;
    }

第四步.查看本地磁盘中前端上传的文件

 

文件上传的四大注意事项:

  1. 为保证服务器安全,上传的文件应该放在外界无法直接访问的目录下,比如放在WEB-INF目录下
  2. 为防止上传的文件发生覆盖,要为每一个上传的文件生成一个唯一的文件名
  3. 限制上传文件的大小
  4. 限制上传文件的类型,通过文件的后缀名判断是否合法
posted @ 2021-12-14 13:50  从0开始丿  阅读(110)  评论(0编辑  收藏  举报