欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

文件上传的 Java 实现详解 - ServletFileUpload 负责处理上传的文件数据,表单中的每个输入都被封装成一个 FileItem 对象,在解析请求时需要使用 ServletFileUpload 对象在解析请求时需要一个 DiskFileItemFactory 对象。因此,我们需要构建 DiskFileItemFactory 对象,并通过 ServletFileUpload 对象的构造函数或 setFileItemFactory 方法设置 ServletFileUpload 对象的 fileItemFactory 对象。 通过 ServletFileUpload 对象的构造函数方法或 setFileItemFactory 方法。 ServletFileUpload 类

最编程 2024-06-23 11:18:26
...

ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象中,使用其parseRequest(HttpServletRequest)方法

可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回,使用该方法处理上传文件简单易用
trim()方法去掉首尾空格

实现过程

前端提交form表导致FileServlet中
在这里插入图片描述

我们在FileServlet中实现上传文件的功能
1.首先
判断上传的文件是普通表单还是带文件的表单

 if(!ServletFileUpload.isMultipartContent(request)){
            return;//终止方法运行,说明这是一个普通的表单,直接返回
  }

2.创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件

 String uploadPath=this.getServletContext().getRealPath("/WEB-INF/upload");
        File uploadFile=new File(uploadPath);
        if(!uploadFile.exists()){
            uploadFile.mkdir();//创建这个目录
        }
        System.out.println("创建目录成功");

3.缓存,临时文件:文件超过规定大小,被弄成临时文件,过几天自动删除,或者提醒用户转存为永久

String tmpPath=this.getServletContext().getRealPath("/WEB-INF/upload");
        File file=new File(tmpPath);
        if(!file.exists()){
            file.mkdir();//创建这个目录
        }

4.处理上传的文件,一般需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于commons-io组件:
????创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的:
DiskFileItemFactory factory=new DiskFileItemFactory();
通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中:
factory.setSizeThreshold(1024*1024);
actory.setRepository(file);

DiskFileItemFactory factory=getDiskFileItemFactory(file);
//======================================================
DiskFileItemFactory getDiskFileItemFactory(File file){
        DiskFileItemFactory factory=new DiskFileItemFactory();
        //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中:
        factory.setSizeThreshold(1024*1024);
        factory.setRepository(file);
        return factory;
    }

5.获取ServletFileload 用来监听
监听文件的上传进度

ServletFileUpload upload=getServletFileUpload(factory);
//=====================================================
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);
        //设置总共能够上传文件的大小
        //1024=1kb*1024=1M*10=10M
        upload.setSizeMax(1024*1024*10);
        return  upload;
    }

6.处理上传文件

String msg=uploadParseRequest(upload,request,uploadPath);
//=======================================================
String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request,String uploadPath){
        String msg="上传失败";
        try {
            List<FileItem> fileItems=upload.parseRequest(request);
            //fileItem每一个表单对象
            for (FileItem fileItem : fileItems) {
                //判断上传的文件是普通的表单还是带文件的表单
                if(fileItem.isFormField()){
                    //getFiledName指的是前端表单控件的name;
                    String name=fileItem.getFieldName();
                    String value=fileItem.getString("UTF-8");
                    System.out.println(name+":"+value);
                }else{
                    //如果是文件表单
                    //1.处理文件=================
                    String uploadFileName=fileItem.getName();
                    System.out.println("上传的文件名:"+uploadFileName);
                    //可能存在文件名不合法的情况
                    if(uploadFileName.trim().equals("")||uploadFileName==null){
                        continue;
                    }
                    //获得上传的文件名 /images/gurl/paojie.png
                    String fileName=uploadFileName.substring(uploadFileName.lastIndexOf("/")+1);
                    //获得文件的后缀名
                    String fileExtName=uploadFileName.substring(uploadFileName.lastIndexOf(".")+1);
                    /*
                     * 如果文件的后缀名fileExtName不是我们所要的
                     * 就直接return 不处理,告诉用户文件类型不对
                     * */
                    //可以使用UUID(唯一识别的通用码),保证文件名唯一
                    //UUID.randomUUID() 随机生成一个唯一识别的通用码
                    //网络传输中的东西都需要序列化,
                    //POJO,实体类只能在本机上用,如果想要在多个电脑上运行,传输===》需要把对象都序列化了
                    //implements Serializable 没有方法的接口-》标记接口。JVM虚拟机在运行的时候,JVM的本地方法栈-- native->c++
                    //JNI=java Native Interface->java 本地化接口
                    //Java栈
                    //UUID 通过位运算,生成随机序列号保证不重复性
                    String uuidPath = UUID.randomUUID().toString();
                    //2.存放地址=================
                    //存到哪?uploadPath
                    //文件真实存在的路径realPath
                    String realPath=uploadPath+"/"+uuidPath;
                    //给每个文件创建一个对应的文件夹
                    File realPathFile=new File(realPath);
                    if(!realPathFile.exists()){
                        realPathFile.mkdir();
                    }
                    //3.文件传输=================
                    //获取文件上传的流
                    InputStream inputStream=fileItem.getInputStream();
                    //创建一个文件输出流
                    //realPath=真实的文件夹
                    //差了一个文件,加上输出文件的名字+"/"+uuidFileName
                    FileOutputStream fos=new FileOutputStream(realPath+"/"+fileName);
                    //创建一个缓冲区
                    byte[] buffer=new byte[1024*1024];
                    //判断是否读取完毕
                    int len=0;
                    //如果大于0说明还存在数据
                    while((len=inputStream.read(buffer))>0){
                        fos.write(buffer,0,len);
                    }
                    msg="上传文件成功";
                    //关闭流
                    fos.close();
                    inputStream.close();
                    fileItem.delete();//上传文件成功,清除临时文件

                }

            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return  msg;
    }

7.最后得到文件上传的结果利用Servlet请求转发

 //servlet请求转发消息
        request.setAttribute("msg",msg);
        request.getRequestDispatcher("info.jsp").forward(request,response);

完整代码

package com.lding.servlet;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.List;
import java.util.UUID;

/**
 * @program: FileTransport
 * @description: ${description}
 * @author: 王丁
 * @date: 2021-11-11 11:25
 **/
public class FileServlet extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        System.out.println("进入FileServlet");
        //判断上传的文件是普通表单还是带文件的表单
        if(!ServletFileUpload.isMultipartContent(request)){
            return;//终止方法运行,说明这是一个普通的表单,直接返回
        }
        //创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件
        String uploadPath=this.getServletContext().getRealPath("/WEB-INF/upload");
        File uploadFile=new File(uploadPath);
        if(!uploadFile.exists()){
            uploadFile.mkdir();//创建这个目录
        }
        System.out.println("创建目录成功");
        //缓存,临时文件
        //文件超过规定大小,被弄成临时文件,过几天自动删除,或者提醒用户转存为永久
        String tmpPath=this.getServletContext().getRealPath("/WEB-INF/upload");
        File file=new File(tmpPath);
        if(!file.exists()){
            file.mkdir();//创建这个目录
        }
        //处理上传的文件,一般需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
        //但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于commons-io组件:
        /*
            ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileTtem对象
            在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象
            所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象
            通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象
            对象的fileItemFactory属性
         */

        DiskFileItemFactory factory=getDiskFileItemFactory(file);
        //        //????监听文件上传的进度
        ServletFileUpload upload=getServletFileUpload(factory);
        //3.????处理上传文件
        String msg=uploadParseRequest(upload,request,uploadPath);
   

        //servlet请求转发消息
        request.setAttribute("msg",msg);
        request.getRequestDispatcher("info.jsp").forward(request,response);


    }
    DiskFileItemFactory getDiskFileItemFactory(File file){
        DiskFileItemFactory factory=new DiskFileItemFactory();
        //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中:
        factory.setSizeThreshold(1024*1024);
        factory.setRepository(file);
        return factory;
    }
    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);
        //设置总共能够上传文件的大小
        //1024=1kb*1024=1M*10=10M
        upload.setSizeMax(1024*1024*10);
        return  upload;
    }
    String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request,String uploadPath){
        String msg="上传失败";
        try {
            List<FileItem> fileItems=upload.parseRequest(request);
            //fileItem每一个表单对象
            for (FileItem fileItem : fileItems) {
                //判断上传的文件是普通的表单还是带文件的表单
                if(fileItem.isFormField()){
                    //getFiledName指的是前端表单控件的name;
                    String name=fileItem.getFieldName();
                    String value=fileItem.getString("UTF-8");
                    System.out.println(name+":"+value);
                }else{
                    //如果是文件表单
                    //1.处理文件=================
                    String uploadFileName=fileItem.getName();
                    System.out.println("上传的文件名:"+uploadFileName);
                    //可能存在文件名不合法的情况
                    if(uploadFileName.trim().equals("")||uploadFileName==null){
                        continue;
                    }
                    //获得上传的文件名 /images/gurl/paojie.png
                    String fileName=uploadFileName.substring(uploadFileName.lastIndexOf("/")+1);
                    //获得文件的后缀名
                    String fileExtName=uploadFileName.substring(uploadFileName.lastIndexOf(".")+1);
                    /*
                     * 如果文件的后缀名fileExtName不是我们所要的
                     * 就直接return 不处理,告诉用户文件类型不对
                     * */
                    //可以使用UUID(唯一识别的通用码),保证文件名唯一
                    //UUID.randomUUID() 随机生成一个唯一识别的通用码
                    //网络传输中的东西都需要序列化,
                    //POJO,实体类只能在本机上用,如果想要在多个电脑上运行,传输===》需要把对象都序列化了
                    //implements Serializable 没有方法的接口-》标记接口。JVM虚拟机在运行的时候,JVM的本地方法栈-- native->c++
                    //JNI=java Native Interface->java 本地化接口
                    //Java栈
                    //UUID 通过位运算,生成随机序列号保证不重复性
                    String uuidPath = UUID.randomUUID().toString();
                    //2.存放地址=================
                    //存到哪?uploadPath
                    //文件真实存在的路径realPath
                    String realPath=uploadPath+"/"+uuidPath;
                    //给每个文件创建一个对应的文件夹
                    File realPathFile=new File(realPath);
                    if(!realPathFile.exists()){
                        realPathFile.mkdir();
                    }
                    //3.文件传输=================
                    //获取文件上传的流
                    InputStream inputStream=fileItem.getInputStream();
                    //创建一个文件输出流
                    //realPath=真实的文件夹
                    //差了一个文件,加上输出文件的名字+"/"+uuidFileName
                    FileOutputStream fos=new FileOutputStream(realPath+"/"+fileName);
                    //创建一个缓冲区
                    byte[] buffer=new byte[1024*1024];
                    //判断是否读取完毕
                    int len=0;
                    //如果大于0说明还存在数据
                    while((len=inputStream.read(buffer))>0){
                        fos.write(buffer,0,len);
                    }
                    msg="上传文件成功";
                    //关闭流
                    fos.close();
                    inputStream.close();
                    fileItem.delete();//上传文件成功,清除临时文件

                }

            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return  msg;
    }
    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

    }
}

运行结果

在这里插入图片描述

如果对您有帮助,免费的赞点一个~感谢????

推荐阅读