简介

对于文件上传,客户端需要一个上传文件的表单 服务端则需要在接收到表单后通过IO将其存储到磁盘里。

客户端

主要需要准备一个表单 alt

分析请求

alt

服务器端(基于Servlet)

  1. 通过request获取请求体的内容

  2. 解析请求体 多部件上传的特点是,每个input都是一个表单项.

    根据分隔符将请求中所有的内容,切割成数组,数组中的每一个元素 都是一个表单项

  3. 遍历数组,分清楚那个是普通的表单项, 哪个是 文件上传项

    如何区分? 判断是否有 filename

  4. 获取到普通表单项中的内容,通过属性name获取

  5. 获取文件上传项内容

    文件名: filname = aaa.txt

    文件内容:

  6. 使用IO将文件内容,保存到服务器中

FileUpload

是一个maven的dependency

FileUpload使用步骤:

​ 1、创建磁盘文件项工厂

​ 2、创建文件上传的核心类

​ 3、解析request---获得文件项集合

​ 4、遍历文件项集合

​ 5、判断普通表单项/文件上传项

示例代码,展示了需要用到的API。注意在IO的时候使用了IOutils,这也是一个maven的dependency。当然不用也没问题,我们已经获得了输入流和输出流,所以接下来还是很好做的。

@WebServlet("/upload")
public class FileUploadServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        try {
            //1.创建磁盘文件项工厂
            DiskFileItemFactory factory = new DiskFileItemFactory();

            //2.创建文件上传核心类
            ServletFileUpload upload = new ServletFileUpload(factory);
            //2.1 设置上传文件名的编码
            upload.setHeaderEncoding("utf-8");
            //2.2 判断表单是否是文件上传表单
            boolean multipartContent = upload.isMultipartContent(req);
            //2.3 是文件上传表单
            if(multipartContent){

                //3. 解析request ,获取文件项集合
                List<FileItem> list = upload.parseRequest(req);

                if(list != null){
                    //4.遍历获取表单项
                    for (FileItem item : list) {
                        //5. 判断是不是一个普通表单项
                        boolean formField = item.isFormField();
                        if(formField){
                            //普通表单项, 当 enctype="multipart/form-data"时, request的getParameter()方法 无法获取参数
                            String fieldName = item.getFieldName();
                            String value = item.getString("utf-8");//设置编码
                            System.out.println(fieldName + "=" + value);
                        }else{

                            //文件上传项
                            //文件名
                            String fileName = item.getName();

                            //避免图片名重复 拼接UUID
                            String newFileName = UUIDUtils.getUUID()+"_"+ fileName;
 
                            //获取输入流
                            InputStream in = item.getInputStream();

                            //创建输出流 输出到H盘
                            FileOutputStream fos = new FileOutputStream("H:/upload/" +newFileName);

                            //使用工具类IOUtils,copy文件
                            IOUtils.copy(in,fos);

                            //关闭流
                            fos.close();
                            in.close();

                        }

                    }
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

}

部署图片到tomcat(涉及到idea)

  1. 将项目部署到webapps

将部署方式改变为 war模式,把项目部署在tomcat的webapps下(在idea里只需要简单切换一下即可)

  • idea中部署项目两种方式
    • war模式:将项目以war包的形式上传真实到服务器的webapps目录中;
    • war exploded模式:仅仅是目录的映射,就相当于tomcat在项目源文件夹中启动一样;

2.在webapps中创建upload目录

upload目录专门用来保存上传过来的图片

3.修改代码,将图片上传到服务器

  • 修改图片的输出路径
    1. 获取到项目的运行目录信息
    2. 截取到webapps的 目录路径
    3. 拼接输出路径,将图片保存到upload
@Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

       try {
           //1.创建磁盘文件项工厂
           DiskFileItemFactory factory = new DiskFileItemFactory();

           //2.创建文件上传核心类
           ServletFileUpload upload = new ServletFileUpload(factory);
           //2.1 设置上传文件名的编码
           upload.setHeaderEncoding("utf-8");
           //2.2 判断表单是否是文件上传表单
           boolean multipartContent = upload.isMultipartContent(req);
           //2.3 是文件上传表单
           if(multipartContent){

               //3. 解析request ,获取文件项集合
               List<FileItem> list = upload.parseRequest(req);

               if(list != null){
                   //4.遍历获取表单项
                   for (FileItem item : list) {
                       //5. 判断是不是一个普通表单项
                       boolean formField = item.isFormField();
                       if(formField){
                           //普通表单项, 当 enctype="multipart/form-data"时, request的getParameter()方法 无法获取参数
                           String fieldName = item.getFieldName();
                           String value = item.getString("utf-8");//设置编码
                           System.out.println(fieldName + "=" + value);
                       }else{

                           //文件上传项
                           //文件名
                           String fileName = item.getName();
                           //避免图片名重复 拼接UUID
                           String newFileName = UUIDUtils.getUUID()+"_"+ fileName;

                           //获取上传文件的内容
                           InputStream in = item.getInputStream();

                           String path = this.getServletContext().getRealPath("/");
                           
                           //获取到 webapps路径,
                           String webappsPath = path.substring(0, path.indexOf("projectName"));
                           OutputStream out = new FileOutputStream(webappsPath+"/upload/"+newFileName);
                           //拷贝文件到服务器
                           IOUtils.copy(in,out);

                           out.close();
                           in.close();
                       }

                   }
               }
           }
       } catch (FileUploadException e) {
           e.printStackTrace();
       }

   }

补充

代码里用到了一个UUIDUtils,其实就是自己写的一个类而已。

public class UUIDUtils {

   //获取唯一ID的 方法
   public static String getUUID() {

       return UUID.randomUUID().toString().replace("-", "");
   }

}