文件的上传与下载

一、文件的上传

文件的上传,是通过表单form的形式进行的,正常的提交流程需要满足3个条件,即文件上传从头至尾的步骤如下:

1.1 表单进行限制:

中文件的属性设置包含如下:

  • 指定 enctype = multipart/form-data
  • 指定 method = post
<form action="/day12/uploadServlet2" method="post" enctype="multipart/form-data">
    用户名:<input name="username" ><br>
    上传头像:<input type="file" name="f" ><br>
    <input type="submit" value="提交">
form>

设置后,HTTP的请求体的信息如下:

-----------------------------7df29b39704fa
Content-Disposition: form-data; name="username"
zhangsan
-----------------------------7df29b39704fa
Content-Disposition: form-data; name="f"; filename="Desert.jpg"
Content-Type: image/jpeg
<二进制文件数据未显示>
---------------------------7df29b39704fa--

1.2对Servlet的限制

  • 不能使用getParameter获取请求参数。即使要使用 获取的也是null
  • 使用 getInputStream()获取消息体数据
    然后解析消息体,就可以来获取我们需要的数据了

1.3解析数据:

解析数据分为普通的表单数据和文件的表单数据,其中文件的表单数据解析方式和XML的解析步骤差不多

  1. 导包 file-upload 组件:apache
    • commons-fileupload-1.2.1.jar
    • commons-io-1.4.jar
  2. 创建解析器工厂
  3. 获取解析器
  4. 解析request。获取 List
  5. 遍历集合
  6. 使用FileItem方法获取数据
    • 普通表单项
      • getString(String encoding):获取普通表单项的值
    • 文件表单项
      • getName():获取文件名称
      • getSize():获取文件大小
      • getContentType():获取文件类型
      • getOutputStream():获取文件字节数据
      • write(java.io.File file) :将文件数据写到硬盘上
    • 公共方法
      • isFormField():判断是否为普通表单项
      • getFieldName():获取表单项的名称
//1.创建解析器工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//2.获取解析器
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("utf-8");
//3.解析request
List fileItems = upload.parseRequest(request);
//4.遍历
for (FileItem fileItem : fileItems) {
    System.out.println("--------------------");
    String fieldName = fileItem.getFieldName();
    System.out.println(fieldName);
    if(fileItem.isFormField()){
        //普通表单项
        String value = fileItem.getString("utf-8");
        System.out.println(value);
    }else{
        //文件表单项
        String name = fileItem.getName();
        long size = fileItem.getSize();
        String contentType = fileItem.getContentType();
        String filename = "/"+UUIDUtils.getUUID() + "_" + name;
        fileItem.write(new File(this.getServletContext().getRealPath("/upload"+filename)));

        System.out.println(name+size+contentType);
    }
}

二、文件的下载

  1. 超链接直接指向资源
    如果浏览器有解析引擎支持文件格式,就直接在浏览器中打开。反之,则弹出下载提示框。这各方式不对响应头进行处理,所以打开方式不可以控制。
<a href="/day12_2/a.jpg">图片a>
<a href="/day12_2/a.avi">电影a>
  1. 通过response输出流
    这种方式,把请求提交到servlet进行处理。通过servlet设置response响应头的方式,可以控制浏览器的打开方式,从而可以让用户选择“打开”或者“保存”。
 <a href="/day12_2/download?filename=哈哈.jpg">图片a>
 <a href="/day12_2/download?filename=a.avi">电影a>
  • 两个响应头:
    • content-disposition:attachment;filename=xxx
      • inline:默认值。在浏览器中打开
      • attachment;filename=xxx:弹出下载提示框
    • content-type:文件的格式
  • 一个流:文件关联后,通过response输出流,把文件
// 1.获取文件名称
    String filename = request.getParameter("filename");
    filename = new String(filename.getBytes("iso-8859-1"), "utf-8");
    // 2.通过名称获取文件对象
    String filepath = this.getServletContext().getRealPath("/" + filename);
    // 3.创建输入流关联文件
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
            filepath));
    // 4.设置两个头
    //获取浏览器的版本信息,解决浏览器的兼容性问题
    String agent = request.getHeader("user-agent");
    if (agent.contains("MSIE")) {
        // IE浏览器
        filename = URLEncoder.encode(filename, "utf-8");
        filename = filename.replace("+", " ");
    } else if (agent.contains("Firefox")) {
        // 火狐浏览器
        BASE64Encoder base64Encoder = new BASE64Encoder();
        filename = "=?utf-8?B?"
                + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
    } else if (agent.contains("Chrome")) {
        // google浏览器
        filename = URLEncoder.encode(filename, "utf-8");
    } else {
        // 其它浏览器
        filename = URLEncoder.encode(filename, "utf-8");
    }

    /*// 中文名称在浏览器的下载提示框中不显示问题
    filename = URLEncoder.encode(filename, "utf-8");*/
    response.setHeader("content-disposition", "attachment;filename="
            + filename);
    response.setContentType(this.getServletContext().getMimeType(filename));
    // 5.将输入流数据 拷贝到 response输出流中
    IOUtils.copy(bis, response.getOutputStream());

你可能感兴趣的:(Java_Web)