javaweb上传文件

目录

1.简述

2.原理讲解

3.代码如下(含注释)

3.1获得DiskFileItemFactory对象

3.2获得ServletFileUpload对象 

 3.3上传文件 

3.4 doPost()

4.运行结果


1.简述

在一个web项目中,用户向工程中上传文件是十分常见的操作,如头像设置、背景图片设置等。服务器在保存用户上传的文件的时候,需要解决以下四个问题:1.用户上传的文件不能直接通过在地址栏输入url去访问;2.用户上传的文件不能被覆盖(在同一个文件夹下的同名文件会被覆盖);3.限制上传文件的最大值;4.可以限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。

这篇文章将简单讲解如何在Javaweb项目上传文件并解决上面提到的四个问题

2.原理讲解

上传文件的表单如图所示

一般在处理上传文件的时候,用流来处理,但是这样的话需要自己实现网络通信底层,太麻烦了,这里使用apache的commons-io组件来完成。

ServletFileUpload类负责处理上传的文件数据,并将表单中的每个输入项封装成FileItem对象。在获取ServletFileUpload对象的时候,需要一个DiskFileItemFactory对象

通过ServletFileUpload对象获得FileItem对象后,遍历所有的FileItem对象,判断每个对象只是简单的表单元素还是包含了文件,若包含了文件,将文件进行处理保存,并转发到上传信息的页面就好了。

为了避免用户通过输入url地址直接访问到服务器上的文件,可以设置拦截器,这里就直接把文件存储在WEB-INF目录下了。为了防止文件覆盖,项目中使用了UUID这个类来获得一个唯一的标识符,利用这个唯一的标识符来存储文件就不会发生覆盖的情况了。

3.代码如下(含注释)

3.1获得DiskFileItemFactory对象

    public DiskFileItemFactory getDiskFileItemFactory(File tempFile){
        DiskFileItemFactory factory = new DiskFileItemFactory();
//        为上传文件设置一个大小限定,当文件超过这个大小的时候,缓存在暂存区
        factory.setSizeThreshold(1024*1024); //大小为1M
        factory.setRepository(tempFile); //设置暂存区
        return factory;
    }

3.2获得ServletFileUpload对象 

    public ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){
        ServletFileUpload upload = new ServletFileUpload(factory);
        upload.setProgressListener(new ProgressListener() {
            @Override
//            pBytesRead:已经读取的文件大小
//            pContentLength:文件总大小
            public void update(long pBytesRead, long pContentLength, int pItems) {
                System.out.println("总大小:"+ pContentLength + ";已上传:" + pBytesRead);
            }
        });
//        处理乱码问题
        upload.setHeaderEncoding("UTF-8");
//        设置单个文件的最大值
        upload.setFileSizeMax(1024*1024*10);
//        设置总共能够上传文件的大小
        upload.setSizeMax(1024*1024*10);

        return upload;
    }

 3.3上传文件 

public void uploadFile(HttpServletRequest req, HttpServletResponse resp,ServletFileUpload upload, String uploadPath) throws IOException, ServletException {
        String msg = "文件上传失败";

//        把前端请求解析,封装成一个FileItem对象,从ServletFIleUpload对象中获取
        List<FileItem> fileItems = null;
        try {
            fileItems = upload.parseRequest(req);
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
        for (FileItem fileItem : fileItems) {
//            当前FileItem对象只是一个表单对象
            if(fileItem.isFormField()){
                String name = fileItem.getFieldName(); //获得表单控件的name值
                String value = fileItem.getString("UTF-8");//获得文本,处理乱码
                System.out.println(name+" :"+value);
            }else {
//            当前FileItem包含文件
//                    ===========================处理文件===============================
                String uploadFileName = fileItem.getName();
                if(uploadFileName.trim().equals("") || uploadFileName==null){
                    continue;
                }
                //                获得上传的文件名
                String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/")+1);
//                获得上传的文件后缀
                String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".")+1);

//                使用UUID获得一个唯一的识别通用码,保证文件名唯一
//                网络传输中的东西,都需要序列化
//                实体类如果想要在多个电脑上运行,需要进行传输===》使用序列号
                String uuidPath = UUID.randomUUID().toString();

//                ==========================存放地址==========================================
                String readPath = uploadPath+"/"+uuidPath;
//                给每个文件创建也给对应的文件夹
                File realPathFile = new File(readPath);
                if(!realPathFile.exists()){
                    realPathFile.mkdir();
                }

//               ===========================文件传输==========================================
//                获得文件上传的流
                InputStream inputStream = fileItem.getInputStream();
//                创建一个文件输出流
                FileOutputStream fos = new FileOutputStream(readPath+"/"+fileName);
//                创建一个缓冲区
                byte[] buffer = new byte[1024*1024];
//                判断是否读取完毕
                int len = 0;
                while ((len=inputStream.read(buffer))>0){
                    fos.write(buffer, 0, len);
                }
//                关闭流
                fos.close();
                inputStream.close();
            }
            msg = "文件上传成功";
        }
        req.setAttribute("msg", msg);
        req.getRequestDispatcher("info.jsp").forward(req, resp);
    }

3.4 doPost()

   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        判断上传的文件是普通表单还是带文件的表单
        String msg = "文件上传失败";
        if(!ServletFileUpload.isMultipartContent(req)){
            return;
        }

//        创建上传文件的保存路径,建议放在web-inf路径下以保证安全,用户无法直接访问上传的文件
        String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
        File uploadFile = new File(uploadPath);
        if(!uploadFile.exists()){//如果文件夹不存在,则创建改文件夹
            uploadFile.mkdir();
        }

//        缓存临时文件
//        临时路径,如果文件超过了预期大小,就放到临时文件夹下
        String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
        File tmpFile = new File(tmpPath);
        if(!tmpFile.exists()){
            tmpFile.mkdir();
        }

//        处理上传的文件,一般需要通过流来获取
//        此处使用apache的组件来实现  commons-io

        /*
        * ServletFileUpload负责处理上传的文件数据,并将表单中的每个输入项封装成fileItem对象
        * 在使用ServletFileUpload对象解析请求时需要DIskFileItemFactory对象
        * 所有,需要在进行解析工作前构造好DiskFileItemFactory对象*/

//       1. 创建DiskFileIntemFactory对象,处理文件上传路径或者大小限制
        DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile);

//      2。获取ServletFileUpload
        ServletFileUpload upload = getServletFileUpload(factory);

//        3.处理上传文件
        uploadFile(req, resp,upload, uploadPath);
    }

补充:通过表单上传文件,get方法对上传文件的大小有限制,post方法没有限制,所以一般使用post方法。而且使用get方法的话在获取ServletFileUpload时会出错。另外,表单如果包含一个文件上传输入的话,这个表单的enctype属性就必须设置为multipart/form-data。

4.运行结果

通过表单提交了文件后,可以在tomcat目录下找到项目文件夹,在WEB-INF目录下就多出了upload和temp这两个文件夹,上传的文件都保存在这两个文件夹下面。

  • 8
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值