zoukankan      html  css  js  c++  java
  • 文件上传和下载

    一、文件的上传和下载
      1、文件上传的原理分析
        1.1文件上传的必要前提:
          a、提供form表单,method必须是post
          b、form表单的enctype必须是multipart/form-data
          c、提供input type="file"类的上传输入域
        1.2enctype属性
          作用:告知服务器请求正文的MIME类型。(请求消息头:Content-Type作用是一致的)
          可选值:


            application/x-www-form-urlencoded(默认):
          正文:name=admin&password=123
          服务器获取数据:String name = request.getParameter("name");

            multipart/form-data:
          正文:对每个域分开上传
          服务器获取数据:request.getParameter(String)方法获取指定的表单字段字符内容,
                  但文件上传表单已经不在是字符内容,而是字节内容,所以失效。
                  所以使用request.getInputStream()获取数据


          文件上传:解析请求正文的每部分的内容。

      2、借助第三方的上传组件实现文件上传
        2.1 fileupload概述
            fileupload是由apache的commons组件提供的上传组件。它最主要的工作就是帮我们解析request.getInputStream()。
          导入commons-fileupload相关jar包
            commons-fileupload.jar,核心包;
            commons-io.jar,依赖包。

        2.2 fileupload的核心类有:
          DiskFileItemFactory、ServletFileUpload、FileItem。

        2.3 fileupload简单应用
          使用fileupload组件的步骤如下:
            1. 创建工厂类DiskFileItemFactory对象:
              DiskFileItemFactory factory = new DiskFileItemFactory()
            2. 使用工厂创建解析器对象:
              ServletFileUpload fileUpload = new ServletFileUpload(factory)
            3. 使用解析器来解析request对象:
              List<FileItem> list = fileUpload.parseRequest(request)

          

          DiskFileItemFactory对象的方法

            setRepository(new File("f:\")): 指定临时文件的存储目录

          ServletFileUpload对象的方法

            (static)isMultipartContent(request) : 判断表单是否支持文件上传。即:enctype="multipart/form-data"
            setHeaderEncoding("UTF-8") : 解决上传表单项乱码问题
            setFileSizeMax(1024*1024*3) :限制单个文件大小为3M
            setSizeMax(1024*1024*6) :限制全部文件大小为3M


          FileItem对象对应一个表单项(表单字段)。可以是文件字段或普通字段
            boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回false,说明是文件字段;
            String getFieldName():获取字段名称,例如:<input type=”text” name=”username”/>,返回的是username;
            String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件;
            String getName():获取文件字段的文件名称;(a.txt)
            String getContentType():获取上传的文件的MIME类型,例如:text/plain。
            int getSize():获取上传文件的大小;
            InputStream getInputStream():获取上传文件对应的输入流;
            void write(File):把上传的文件保存到指定文件中。
            delete(): 删除在上传大文件时产生的临时存储文件。


      3、文件上传时要考虑的几个问题(经验分享)

        a、解决获得客户端文件名时可能带有全路径的问题(造成服务端存盘有双根目录)

          filename = FilenameUtils.getName(filename);
        a、保证服务器的安全
          把保存上传文件的目录放在用户直接访问不到的地方。
          String directoryRealPath = this.getServletContext().getRealPath("/WEB-INF/upload");

        b、避免文件被覆盖
          让文件名唯一即可
          filename = UUID.randomUUID() + "_" + filename; (或者)
          filename.substring(filename.lastIndexOf(File.separator)+1);
        c、避免同一个文件夹中的文件过多
          方案一:按照日期进行打散存储目录
          private String makeChildDirectory(File storeDirectory) {

            SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd");
            String dateDirectory = sdf.format(new Date());
            //只管创建目录 File file = new File(storeDirectory,dateDirectory);
            if(!file.exists()){ file.mkdirs(); }

            return dateDirectory;
          }

          方案二:用文件名的hashCode计算打散的存储目录:二级目录
          private String makeChildDirectory(File storeDirectory, String filename) {
            int hashcode = filename.hashCode();// 返回字符转换的32位hashcode码
            System.out.println(hashcode);
            String code = Integer.toHexString(hashcode); // 把hashcode转换为16进制的字符
                                    // abdsaf2131safsd
            System.out.println(code);
            String childDirectory = code.charAt(0) + File.separator+ code.charAt(1); // a/b
                // 创建指定目录
            File file = new File(storeDirectory, childDirectory);
            if (!file.exists()) {
              file.mkdirs();
            }
            return childDirectory;
          }

        d、限制文件的大小:web方式不适合上传大的文件
          单个文件大小:
            ServletFileUpload.setFileSizeMax(字节)
          总文件大小:(多文件上传)
            ServletFileUpload.setSizeMax(字节)

        e、上传字段用户没有上传的问题
          通过判断文件名是否为空即可

        f、临时文件的问题
          DiskFileItemFactory:
          作用:产生FileItem对象
            内部有一个缓存,缓存大小默认是10Kb。如果上传的文件超过10Kb,用磁盘作为缓存。
            存放缓存文件的目录在哪里?默认是系统的临时目录。

            如果自己用IO流实现的文件上传,要在流关闭后,清理临时文件。
            FileItem.delete();

  • 相关阅读:
    Java 8 Lambda 表达式
    OSGi 系列(十二)之 Http Service
    OSGi 系列(十三)之 Configuration Admin Service
    OSGi 系列(十四)之 Event Admin Service
    OSGi 系列(十六)之 JDBC Service
    OSGi 系列(十)之 Blueprint
    OSGi 系列(七)之服务的监听、跟踪、声明等
    OSGi 系列(六)之服务的使用
    OSGi 系列(三)之 bundle 事件监听
    OSGi 系列(三)之 bundle 详解
  • 原文地址:https://www.cnblogs.com/soficircle/p/6953529.html
Copyright © 2011-2022 走看看