javaweb上传文件

目录

1.简述

2.原理讲解

3.代码如下(含注释)

3.1获得DiskFileItemFactory对象

3.2获得ServletFileUpload对象 

 3.3上传文件 

3.4 doPost()

4.运行结果


1.简述

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

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

2.原理讲解

上传文件的表单如图所示

javaweb上传文件

 

 

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

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

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

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这两个文件夹,上传的文件都保存在这两个文件夹下面。

 

上一篇:使用Struts 2框架开发登录注册,实现登录注册功能,并实现华氏度和摄氏度的转换


下一篇:APP开发流程详解