zoukankan      html  css  js  c++  java
  • Web基础了解版12-上传下载

    上传

    两个步骤:

    1. 用户在页面中选择要上传的文件,然后将请求提交到Servlet

    2. Servlet收到请求,解析用户上传的文件,然后将文件存储到服务器

    上传文件表单

    <form action="Servlet" method="post" enctype="multipart/form-data">
        <input type="file" name="file" /><br /><br />
        <input type="submit" value="上传" />
    </form>

    注意:

    • 表单的method属性必须为post

    • 表单的enctype属性必须为multipart/form-data

    • 上传文件的控件是intput,type属性为file

    注意:Servelet

    • 当enctype="multipart/form-data" 时,再使用getParamter()获取到内容永远为空。
    • 需要引入解析请求中的参数和文件,这个工具就是commons-fileupload。

    commons-fileupload

    它的作用就是可以从request对象中解析出,用户发送的请求参数和上传文件的流。

    commons-fileupload包依赖commons-io,两个包需要同时导入

    核心类:

    1. DiskFileItemFactory

      1. 工厂类,用于创建ServletFileUpload,设置缓存等

      2. 该类一般直接使用构造器直接创建实例

      3. 方法:

        • public void setSizeThreshold(int sizeThreshold):用于设置缓存文件的大小(默认值10kb)

        • public void setRepository(File repository):用于设置缓存文件位置(默认系统缓存目录)

    2. ServletFileUpload

      1. 该类用于解析request对象从而获取用户发送的请求参数(包括普通参数和文件参数)

      2. 该类需要调用有参构造器创建实例,构造器中需要一个DiskFileItemFactory作为参数

      3. 方法:

        • public List<FileItem> parseRequest(HttpServletRequest request):解析request对象,获取请求参数,返回的是一个List,List中保存的是一个FileItem对象,一个对象代表一个请求参数。

        • public void setFileSizeMax(long fileSizeMax):设置单个文件的大小限制,单位为B。如果上传文件超出限制,会在parseRequest()抛出异常FileSizeLimitExceededException。

        • public void setSizeMax(long sizeMax):限制请求内容的总大小,单位为B。如果上传文件超出限制,会在parseRequest()抛出异常SizeLimitExceededException。

    3. FileItem

      1. 该类用于封装用户发送的参数和文件,也就是用户发送来的信息将会被封装成一个FileItem对象,我们通过该对象获取请求参数或上传文件的信息。

      2. 该类不用我们手动创建,由ServletFileItem解析request后返回。

      3. 方法:

        • String getFieldName():获取表单项的名字,也就是input当中的name属性的值。

        • String getName():获取上传的文件名,普通的请求参数为null。

        • String getString(String encoding):获取内容,encoding参数需要指定一个字符集。

          ① 若为文件,将文件的流转换为字符串。

          ② 若为请求参数,则获取请求参数的value。

        • boolean isFormField():判断当前的FileItem封装的是普通请求参数,还是一个文件。

          ① 如果为普通参数返回:true

          ② 如果为文件参数返回:false

        • String getContentType():获取上传文件的MIME类型

        • long getSize():获取内容的大小

        • write():将文件上传到服务器

    //创建工厂类
    DiskFileItemFactory factory = new DiskFileItemFactory();
    //创建请求解析器
    ServletFileUpload fileUpload = new ServletFileUpload(factory);
    //设置上传单个文件的的大小
    fileUpload.setFileSizeMax(1024*1024*3);
    //设置上传总文件的大小
    fileUpload.setSizeMax(1024*1024*3*10);
    //设置响应内容的编码
    response.setContentType("text/html;charset=utf-8");
    try {
        //解析请求信息,获取FileItem的集合
        List<FileItem> items = fileUpload.parseRequest(request);
        //遍历集合
        for (FileItem fileItem : items) {
            //如果是普通的表单项
            if(fileItem.isFormField()){
                //获取参数名
                String fieldName = fileItem.getFieldName();
                //获取参数值
                String value = fileItem.getString("utf-8");
                System.out.println(fieldName+" = "+value);
                //如果是文件表单项
            }else{
                //获取文件名
                String fileName = fileItem.getName();
                //获取上传路径
                String realPath = getServletContext().getRealPath("/WEB-INF/upload");
                //检查upload文件夹是否存在,如果不存在则创建
                File f = new File(realPath);
                if(!f.exists()){
                    f.mkdir();
                };
                //为避免重名生成一个uuid作为文件名的前缀
                String prefix = UUID.randomUUID().toString().replace("-", "");
                //将文件写入到服务器中
                fileItem.write(new File(realPath+"/"+prefix+"_"+fileName));
                //清除文件缓存
                fileItem.delete();
            }
      } }
    catch (Exception e) { if(e instanceof SizeLimitExceededException){ //文件总大小超出限制 response.getWriter().print("上传文件的总大小不能超过30M"); }else if(e instanceof FileSizeLimitExceededException){ //单个文件大小超出限制 response.getWriter().print("上传单个文件的大小不能超过3M"); } } response.getWriter().print("上传成功");

    下载

    下载文件的关键点:

    1. 服务器以一个流的形式将文件发送给浏览器。

    2. 发送流的同时还需要设置几个响应头,来告诉浏览器下载的信息。

      • 具体响应头如下:

        • Content-Type

          • 下载文件的MIME类型

          • 可以通过servletContext. getMimeType(String file)获取

          • 也可以直接手动指定

          • 使用response.setContentType(String type);

          • 响应头样式:Content-Type: audio/mpeg

        • Content-Disposition

          • 下载文件的名字,主要作用是提供一个默认的用户名

          • 通过response.setHeader("Content-Disposition", disposition)设置

          • 响应头样式:Content-Disposition: attachment; filename=xxx.mp3

        • Content-Length

          • 下载文件的长度,用于设置文件的长处(不必须)

          • 通过response. setContentLength(int len)设置。

          • 设置后样式:Content-Length: 3140995

    3. 接下来需要以输入流的形式读入硬盘上的文件

      • FileInputStream is = new FileInputStream(file);

      • 这个流就是我们一会要发送给浏览器的内容

    4. 通过response获取一个输出流,并将文件(输入流)通过该流发送给浏览器

      • 获取输出流:ServletOutputStream out = response.getOutputStream();

      • 通过输出流向浏览器发送文件(不要忘了关闭输入流)

    步骤演示

    以下步骤都是在同一个Servlet的doGet()方法中编写的

    1.获取文件的流:

    String realPath = getServletContext().getRealPath("/WEB-INF/mp3/中国话.mp3");
    //获取文件的File对象
    File file = new File(realPath);
    //获取文件的输入流
    FileInputStream in = new FileInputStream(file);

    2.获取头信息:

    //获取文件的MIME信息
    String contentType = getServletContext().getMimeType(realPath);
    //设置下载文件的名字
    String filename = "zhongguohua.mp3";
    //创建Content-Disposition信息
    String disposition = "attachment; filename="+ filename ;
    //获取文件长度
    long size = file.length();

    3.设置头信息

    //设置Content-Type
    response.setContentType(contentType);
    //设置Content-Disposition
    response.setHeader("Content-Disposition", disposition);
    //设置文件长度
    response.setContentLength((int)size);

    4.发送文件

    //通过response获取输出流,用于向浏览器输出内容
    ServletOutputStream out = response.getOutputStream();
    //将文件输入流通过输出流输出
    byte[] b = new byte[1024];
    int len = 0;
    while((len=is.read(b))> 0){
        out.write(b, 0, len);
    }
    //最后不要忘记关闭输入流,输出流由Tomcat自己处理,我们不用手动关闭
    is.close();

    乱码

    中文文件名会出现乱码问题。解决此问题的方法很简单,在获取文件名之后为文件名进行编码:

    filename = java.net.URLEncoder.encode(filename,"utf-8");

    火狐浏览器比较特殊需要特殊处理一下。

    1.先要获取客户端信息(通过获取请求头中的User-Agent信息)

    String ua = request.getHeader("User-Agent");

    2.然后判断浏览器版本,做不同的处理

    //判断客户端是否为火狐
    if(ua.contains("Firefox")){
        //若为火狐使用BASE64编码
        filename = "=?utf-8?B?"+new BASE64Encoder().encode(filename.getBytes("utf-8"))+"?=";
    }else{
        //否则使用UTF-8
        filename = URLEncoder.encode(filename,"utf-8");
    }
    String string = new String("你好.jpg".getBytes("gbk"), "iso8859-1");
  • 相关阅读:
    枚举定义三个常量--遍历如下
    初始化和赋值的概念
    javascript 事件
    HTML 5 本地存储
    html5 说明
    JQuery 双击动态编辑
    ThinkPHP 3.2.2 事务
    PHP AJAX JSONP实现跨域请求使用实例
    chorme 插件
    frontend-tools
  • 原文地址:https://www.cnblogs.com/Open-ing/p/12151037.html
Copyright © 2011-2022 走看看