【学习笔记】文件的上传和下载

一、文件的上传

页面

  1. 要有一个 form 标签, method=post 请求
  2. form 标签的 encType 属性值必须为 multipart/form-data 值
  3. 在 form 标签中使用 input type=file 添加上传的文件
  4. 编写服务器代码(Servlet 程序) 接收, 处理上传的数据。

encType=multipart/form-data 表示提交的数据, 以多段(每一个表单项一个数据段) 的形式进行拼接, 然后以二进制流的形式发送给服务器。

  <body>
    <form method="post" enctype="multipart/form-data" action="/servletStudy/fileServlet">
        用户名:<input type="text" name="username"><br/>
        密码:<input type="password" name="pwd"><br/>
        上传文件:<input type="file" name="photo"><br>
      <input type="submit" value="提交">
    </form>
  </body>

导入jar包

commons-fileupload-1.2.1.jar
commons-io-1.4.jar

jar包中常用类

在这里插入图片描述
在这里插入图片描述

servlet程序

public class FileServlet extends HttpServlet {
    
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        req.setCharacterEncoding("utf-8");
        //1 先判断上传的数据是否多段数据(只有是多段的数据, 才是文件上传的)
        if(ServletFileUpload.isMultipartContent(req)){
    
    
            // 创建 FileItemFactory 工厂实现类
            DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
            // 创建用于解析上传数据的工具类 ServletFileUpload 类
            ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
            try {
    
    
                List<FileItem> list = servletFileUpload.parseRequest(req);//解析上传数据 得到每一个表单项 FileItem

                for(FileItem fileItem:list){
    
    //循环判断每个表单项是 普通文件 还是 上传文件
                    if(fileItem.isFormField()){
    
    
                        System.out.println("name值:"+fileItem.getFieldName());
                        System.out.println("value值:"+fileItem.getString("utf-8"));
                    }else{
    
    

                        System.out.println("name值:"+fileItem.getFieldName());
                        System.out.println("上传文件名:"+fileItem.getName());
                        fileItem.write(new File("G://"+fileItem.getName()));
                    }
                }
            } catch (Exception e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

配置web.xml

    <servlet>
        <servlet-name>fileServlet</servlet-name>
        <servlet-class>com.study.service.FileServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>fileServlet</servlet-name>
        <url-pattern>/fileServlet</url-pattern>
    </servlet-mapping>

二、文件的下载

在这里插入图片描述
servlet程序

public class FileServlet extends HttpServlet {
    
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
	    //1 .获取下载的文件名
        String name = "银杏.jpg";

        //2. 读取要下载的文件内容(通过ServletContext获取)
        ServletContext servletContext = getServletContext();

        //4. 获取要下载的文件类型 jpg类型
        String mimeType = servletContext.getMimeType("/file/" + name);

        //5. 回传前,通过响应头告诉客户端返回的数据类型
        resp.setContentType(mimeType);

        // 6. 告诉客户端 该图片用于下载,而不是显示在web页面
        /*
        * Content-Disposition 表示收到的数据怎么处理
        * attachment 表示附件 下载使用
        * filename 指定下载的文件名
        *
        * */
        resp.setHeader("Content-Disposition","attachment;filename="+name);


        InputStream is = servletContext.getResourceAsStream("/file/"+name);//读取文件 输入流
        OutputStream outputStream = resp.getOutputStream();// 回传输出流

        //3. 把下载的数据回传给客户端
        IOUtils.copy(is,outputStream);//读取输入流数据 复制给输出流


    }
}

三、解决中文乱码

方案一

针对 IE 浏览器 或者 是谷歌浏览器。
在这里插入图片描述

方案二

针对火狐浏览器

这时候需要把请求头 Content-Disposition: attachment; filename=中文名
编码成为: Content-Disposition: attachment; filename==?charset?B?xxxxx?=

在这里插入图片描述

判断浏览器

由于不同的浏览器需要不同的编码方式,所以我们需要判断浏览器是什么浏览器。

只需要通过判断请求头中 User-Agent 这个请求头携带过来的浏览器信息即可判断出是什么浏览器。

String ua = request.getHeader(“User-Agent”);
ua = “FireFox” 就是火狐