01_文件下载的概述


     文件下载


            服务器通过网络以流的形式将文件发送到客户端的过程


    应用场景


            电影下载


            音乐下载


            安装文件下载


    实现方式


            方式1


                可以使用超链接来实现文件的下载


                     <a href="要下载文件的地址" >下载</a>


                    注意:如果要下载的文件类型是浏览器支持的类型,浏览器会直接打开这个文件,并不会下载这个文件,比如图片


            方式2


                可以使用代码来实现文件的下载


                     需要有两个头和一个流(IO流)


                        Content-type        设置要下载文件的类型(MIME类型)


                        Content-Disposition    通知浏览器,你不要关心下载文件的类型,什么类型的文件都进行下载操作


                        字节输出流            response.getOutputStream()


                        


    


02_超链接方式实现文件下载的功能


    好处:简单


    缺点:1,必须是浏览器不能识别的格式,否则直接打开


        2,如果资源放在WEB-INF路径下,就没有办法获取


         


03_代码方式实现文件下载的功能




04_ 代码方式实现文件下载的功能优化


//路径
 
    String path = request.getParameter("path");//获取客户端传过来的路径
 
    String realPath = getServletContext().getRealPath("/" + path);//拼接上客户端传过来的路径
 
    //名称
 
    String fileName = new String(request.getParameter("fileName").getBytes("ISO-8859-1"),"UTF-8");
 
    //解决文件名乱码问题
 
    response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); 
 
    
 
    具体步骤:
 
    1,将文件存放的目录和文件名拼接到超链接中
 
        目的:动态的获取文件存放的目录和文件名称
 
        <a href="${pageContext.request.contextPath}/DownloadServlet?path=download&filename=传智播客.jpg" >传智.jpg</a>
 
        
 
    2,在Servlet中使用代码获取文件存放目录和文件名
 
        //获取文件存放目录
 
        String path = request.getParameter("path");
 
        String realPath = getServletContext().getRealPath("/" + path);
 
        //获取文件名称
 
        String fileName = request.getParameter("filename");
 
        
 
   
   3,解决get方式提交中文文件名产生的乱码问题    
  
 
        原因:浏览器使用的UTF-8提交,服务器使用的是ISO-8859-1拼接传过来的数据
 
        做法:打回原形,然后再用正确的编码进行拼接
 
        String fileName = new String(request.getParameter("filename").getBytes("ISO-8859-1"), "UTF-8");
 
        
 
     
 4,解决文件下载时中文文件名乱码的问题
 
        原因:浏览器认为中文是不安全的字符,需要把中文转化成他认为比较安全的字符
 
        做法:使用urlencoding进行编码
 
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") );
 
        
 
        
 
01_文件上传的概述
 
    文件上传
 
            用户将本地文件通过网络上传至服务器的过程
 
    应用场景
 
            相亲网站的照片上传
 
            招聘网站的简历上传
 
    文件上传的技术
 
            jspSmartUpload    应用在jsp上的文件上传和文件下载的组件
 
            
  fileupload        应用在java上的文件上传技术,由Apache开源组织提供(本章学习)
 
            servlet3.0        提供了文件上传的技术
 
            Struts            提供了文件上传的技术
 
    文件上传的必要因素
 
            需要有一个表单
 
            表单的method属性的值必须设置为post
 
            表单的enctype属性的值需要设置为multipart/form-data
 
            表单需要有一个input标签
 
                input标签type属性的值需要设置为file
 
                input标签需要有name属性和值
 
                
 
                
 
02_文件上传的原理分析
 
 
 
 
    <form action="${pageContext.request.contextPath}/Upload2Servlet" method="post" enctype="multipart/form-data"> //application/x-www-form-urlencoded(默认不能用于上传文件)
 
        文件信息:<input type="text" name="info"/>
 
        <br />
 
        用户名:<input type="text" name="username"/>
 
        <br />
 
        文件:<input type="file" name="file01" />
 
        <br />
 
        文件2:<input type="file" name="file02" />
 
        <br />
 
        <input type="submit" value="上传"/>
 
    </form>
 
    
 
     
 enctype(encode type) 编码类型,他规定了发送给服务器之前如何对表单进行编码
 
         
 application/x-www-form-urlencoded: 默认对表单数据进行url编码,不能用于文件上传  %AE%DF
 
        
  multipart/form-data:表单数据由多部分组成,既有文本数据,还有文件,图片这些二进制数据
 
                                       
   
 设置之后,浏览器会将文件以二进制的方式上传,可以实现多种类型的文件上传
 
    
 
 
 
 
03_文件上传入门案例(获取表单提交的数据)
 
    获取表单所提交的数据
 
    获取表单所上传的文件
 
    
 
    1,创建磁盘文件的工场对象
 
    2,创建文件上传的核心对象
 
    3,通过文件上传的核心对象解析请求对象得到一个集合对象,他包含所有的表单项对象
 
    4,遍历这个集合对象,得到每一个表单项对象,然后在判断他是否是普通的表单项
 
    5,如果是普通的表单项,就获取他的name和value的值
 
    6,否则就是文件上传的表单项
 
    
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
        
  //1,创建磁盘文件的工场对象
 
        DiskFileItemFactory dfif = new  
 DiskFileItemFactory();
 
         
 //2,创建文件上传的核心对象
 
        ServletFileUpload upload = new  
 ServletFileUpload(dfif);
 
        
  //3,通过文件上传的核心对象解析请求对象得到一个集合对象,他包含所有的表单项对象
 
        List<FileItem> items = null;
 
        try {
 
            items = upload.parseRequest(request);
 
        } catch (FileUploadException e) {
 
            e.printStackTrace();
 
        }
 
        //4,遍历这个集合对象,得到每一个表单项对象,然后在判断他是否是普通的表单项
 
        if (items != null) {
 
            for (FileItem fileItem : items) {
 
                if (fileItem.isFormField()) {
 
                    
  //5,如果是普通的表单项,就获取他的name和value的值
 
                    String fieldName = fileItem.getFieldName();
 
                    String fileValue = fileItem.getString("UTF-8");
 
                    System.out.println(fieldName);
 
                }else {
 
                    
  //6,否则就是文件上传的表单项
 
                    //获取文件名称
 
                    String fileName = fileItem.getName();
 
                    //获取读取上传文件的输入流
 
                    InputStream is = fileItem.getInputStream();
 
                    
 
                    //设置接收文件的存放目录
 
                    String realPath = getServletContext().getRealPath("/file");
 
                    File file = new File(realPath);
 
                    if (!file.exists()) {
 
                        //如果目录不存在,创建一个
 
                        file.mkdirs();
 
                    }
 
                    //创建输出流对象,用于将接收到的文件存到服务器
 
                    OutputStream os = new FileOutputStream(realPath + "/" + fileName);
 
                    //对接
 
                    IOUtils.copy(is, os);
 
                }
 
            }
 
        }
 
        
 
        
 
    }
 
    
 
    
 
04_文件上传入门案例(获取表单上传的文件)
 
 
 
 
 
 
 
05_DiskFileItemFactory的常用API
 
    DiskFileItemFactory
 
            void    setSizeThreshold(int sizeThreshold) 
 
                设置缓冲区大小
 
            void    setRepository(java.io.File repository) 
 
                设置临时目录
 
                
 
    注意:            
 
        1,如果上传的文件不是很大,先走缓冲区(temp)
 
        2,如果上传文件比较大,超过缓冲区的大小,就不走缓冲区了,他会把文件先上传到临时目录中,再把临时目录中的临时文件复制到file目录中
 
        3,需要把整个文件上传工作完成之后才把临时文件复制到我们指定的File目录中
 
        4,需要先把Tomcat关掉才能手动删掉temp里面的文件
 
        5,临时文件临时目录的作用:是做一些续传的操作
 
    
 
                
 
06_ServletFileUpload的常用API
 
    ServletFileUpload
 
             
 static boolean    isMultipartContent( HttpServletRequest request)  *****重要******
 
                用来判断表单 enctype的属性值是否是mutipart  是返回ture 否则返回 false
 
 
 
 
            public void setFileSizeMax(long fileSizeMax)//设置一个请求中单个文件的大小
 
            public void setSizeMax(long sizeMax) //设置一个请求中所有文件的总大小
 
            
 
    注意:
 
        
  1,工厂对象既可以通过构造方法传递,也可以通过他所对应的set方法传递 
 
            
 
            
 
07_FileItem的常用API
 
    FileItem
 
            long    getSize() 获取表单上传文件的大小
 
                    大于0 用户选择了文件 文件是有内容的  等于0 文件没有内容或者用户没有选择文件            
 
            void    delete()  删除临时文件
 
            
  void    write(java.io.File file) 直接写一个文件  ******重要*******