zoukankan      html  css  js  c++  java
  • javaweb-文件的上传下载

    本文用到的jar:

    文件上传:commons-fileupload-1.2.1.jar;

     commons-io-1.4.jar;

    本文需要掌握的知识:html+dom

    1 文件的上传概述;

    1.1 用户把本地的文件储存到服务器上,就是文件的上传;

    1.2 实现文件的上传(目前而言要使用第三方jar);

      1.2.1 jspSmartupload;

    适用范围:应用在jsp的模型一里(嵌入执行上传下载操作的JSP文件中)  ;

      1.2.2 fileUpload;

         来源:Apache commons下面的开源,免费项目(谢谢老板);

     适用范围:(mvc模式);

    1.3 要使用文件的上传,需要满足三个要求:

      ①表单数据提交,提交方式为post提交;

      ②在表单里有一个文件的上传想<input type=”file” name=”filename”/>

      ③在form里面,要设置一个属性值,enctype,设置为multipart/form-data(必须设置,不然只有一个文件名之类的)

    2  文件上传的原理分析:

    从请求响应信息可知;

    Content-Type:multipart/form-data;

    通过请求正文可以得到结论:

    ①找到分割线;

    ②根据分割线区别不同的项;

    ③普通输入项得到的是值;

    ④文件上传项,得到文件的内容,把内容写到服务器里面一个文件中;

    ⑤使用输入流得到文件上传的内容,使用输出流把文件的内容写到服务器上;

    3,文件上传的代码实现的步骤(固定步骤,照着写就可以了);

      3.1 :创建磁盘文件工厂;

    new DiskFileItemFactory();

      3.2:创建核心上传类;

    new ServletFileUpload(FileItemFactory fileItemFactory);

      3.3:使用核心上传类解析request对象;

    parseRequest(-----request(全类名就不写了));

    返回的是一个List集合,集合中有多个FileItem,泛型为<FileItem>;

      3.4:遍历list集合,得到每个FileItem;

      3.5:判断是普通输入项还是文件上传项;

          Boolean isFormField();

      3.6:如果是普通输入项;如果是文件上传项编写文件上传的代码;

    普通输入项:

    getField():得到普通输入项name的值;

    getString():得到普通输入项里面输入的值;

    文件上传项:

    得到通过表单提交的文件的输入流,getInputStream;

    创建输出流,写出文件到服务器的相应的位置(输出位置要带有盘符,通过

    getServletContext().getRealPath(相对路径)可以获取.为什么要这样做,是因为项目在别的服务器上真实路径就不一定一致了,所以要通过相对路径获取到真实路径);

    4,核心API的学习(主要是一些重要的方法);

    4.1 DiskFileItemFactory(磁盘文件项工厂)(核心上传类,重点在于构造);

    构造方法;

    DiskFileItemFactory(int sizeThreshold,java.io.File repository);

    两个参数:

    第一个参数设置上传文件缓冲区的大小;

    第二个参数.如果上传文件超出了缓冲区,产生临时文件,设置临时文件路径

    (可以看做是先用一个等大小的临时文件做占位,然后数据一步步填充);

    DiskFileItemFactory() 无参构造,也可以设置缓冲区;

    setSizeThreadshold(int sizeThreadshold):设置上传文件的缓冲区(单位是字节byte);

    setRepository(java.io.File repository):设置临时文件路径;

    4.2 ServletFileUpload:核心上传类;

       构造方法;

       ServletFileUpload(FileItemFactory fileItemFactory);

    重要方法:;

    parseRequest(javax.servlet.HttpServletRequest request):解析request对象;

    返回一个list<FileItem>集合,每一个元素都是一个FileItem;

    在他的父类中还有一个很重要的方法;

    setHeaderEncoding(java.lang.String encoding);设置上传文件名称的编码;

    setFileSizeMax(long filesizeMax)”:设置单个文件的大小;

    setSIzeMax(long sizeMax): 设置单个文件的总大小;

    4.3 FileItem:文件项

        Boolea isFormField():判断是否是普通输入项;

    getFieldName():得到普通输入项.name的属性值;

    getString():得到普通输入项的文本值;

    getString(encoding):设置输入项中文本的编码;

    getName():得到上传文件的名称(但是有些浏览器得到的带路径的名称,所以要进行截取操作,);

    getInputStream():得到表单提交的文件输入流;

    Delete():删除临时文件(要在关闭流之后删除);

    5 JS控制多文件的上传

    5.1 需求:在上传的表单里面有两个按钮,一个是上传文件的按钮,一个是增加的按钮,增加上传项.

    点击增加按钮之后,增加一行,一个上传输入项和一个删除的按钮

    点击删除按钮之后,删除该行

    点击上传按钮之后,把当前的文件上传到服务器里面去

     5.2 使用js增加一行和删除一行

    <script type="text/javascript">

    //增加一行

    function addFile(){

    //table里面增加一行

    var table = document.getElementsByTagName("table")[0];

    table.innerHTML+="<tr><td><input type='file' name='filename'/></td><td><input type='button' value='删除' onclick='dele(this)'/><td/><tr/> ";

    }

    //删除一行

    function dele(who){

    //获取当前点击的删除按钮所在的tr

    var tr=who.parentNode.parentNode;

    //拿到爸爸

    var table=tr.parentNode;

    //通过爸爸删除儿子

    table.removeChild(tr);

    }

    </script>

    5.3 使用button提交表单的方法

    //通过按钮提交表单实现上传

    function uploadFile(){

    var form =document.getElementsByTagName("form")[0];

    form.submit();

    }

    5.4 常见问题的解决:

    5.4.1 当已经存在名字重复的文件,再次上传会新文件覆盖原文件

    解决方式:在上传的文件名称里添加一个随机的唯一的字符串,保证每个文件都是唯一的值(可以通过uuid生成,也可以使用毫秒数,不过推荐用uuid更加保险

    //生成一个随机的唯一的id

    String id = UUID.randomUUID().toString();

     JSP页面(为什么我没找到jsp代码选择)

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <form action="${pageContext.request.contextPath }/servlet/Upload2" method="post"  enctype="multipart/form-data">
            <input type="button" value="上传" onclick="uploadFile()"/>
            <input type="button" value="增加" onclick="addFile()"/><hr/>
            <table>
                
            </table>
            <%--
            <input type="file" name="filename"/><input type="button" value="删除"/> 
            --%></form>
    </body>
    <script type="text/javascript">
        //通过按钮提交表单实现上传
        function uploadFile(){
            var form =document.getElementsByTagName("form")[0];
            form.submit();
        }
        //增加一行
        function addFile(){
            //在table里面增加一行
            var table = document.getElementsByTagName("table")[0];
            table.innerHTML+="<tr><td><input type='file' name='filename'/></td><td><input type='button' value='删除' onclick='dele(this)'/><td/><tr/> ";
        }
        //删除一行
        function dele(who){
            //获取当前点击的删除按钮所在的tr
            var tr=who.parentNode.parentNode;
            //拿到爸爸
            var table=tr.parentNode;
            //通过爸爸删除儿子
            table.removeChild(tr);
        }
    </script>
    </html>

    servlet处理页面(对应的图片文件就不放上来了)

    package com.zzx.upload;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.List;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    
    public class Upload2 extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            try {
                //1,創建磁盤文件工廠
                DiskFileItemFactory dff = new DiskFileItemFactory();
                //2,創建核心上傳類
                ServletFileUpload fileupload = new ServletFileUpload(dff);
                fileupload.setHeaderEncoding("utf-8");
                //3,解析对应的请求数据
                List<FileItem> fl = fileupload.parseRequest(request);
                for (FileItem fileItem : fl) {
                     //判断是否是普通输入项
                    if(fileItem.isFormField()){
                        //如果是普通输入项,就得到普通输入项name的属性值,和输入的值
                        String name = fileItem.getFieldName();
                        String value = fileItem.getString();
                        System.out.println(name + ":" + value);
                    }else{
                        //如果是文件上传项
                        //获取上传的文件名称,但是有的浏览器里面带的是带路径的名称
                        String filename = fileItem.getName();
                        //优化,判断是否带/,如果带"/"就进行截取,否则就直接用
                        int lens=filename.lastIndexOf("/");
                        if(lens!=-1){
                            filename=filename.substring(lens+1);
                        }
                        //获取文件上传的输入流
                        InputStream is =fileItem.getInputStream();
                        //得到文件夹带盘符的路径
                        String path = getServletContext().getRealPath("/upload");
                        //输出流
                        OutputStream os =new FileOutputStream(path + "/" + filename);
                        //流对接
                        int len=0;
                        byte[]arr =new byte[1024*8];
                        while((len = is.read(arr))!=-1){
                            os.write(arr,0,len);
                        }
                        //关流
                        is.close();
                        os.close();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            doGet(request, response);
        }
    
    }

    6 文件的下载:

    6.1 把服务器上文件保存到本地硬盘,这个过程称为文件的下载

    6.2 文件下载的实现方式:

      6.2.1:  实现超链接的文件下载

    弊端:有的文件无法实现下载,而是显示在页面上(比如图片)

          6.2.2:  通过代码实现文件下载

    无论什么格式的文件都可以下载

    实现步骤:

    0:设置要下载的文件MIME类型(可选)

    第一步:设置头信息,Content-Disposition,无论什么格式,都是以下载的方法打开

    第二步:服务器得到文件的输入流

    第三步:创建输出流,写出到浏览器

    第四步:流对接

    具体代码:

    6.3 常见问题:

    6.3.1 当文件名携带中文的时候(中文名称会乱码,不显示之类的问题)

            6.3.2 原因:不同浏览器编码不同

            ie浏览器采用的是url编码,

            火狐浏览器采用的是base64编码,

       6.3. 3  ① 区分不同的浏览器

     通过请求头 User-Agent,得到当前浏览器的请求类型

      ②根据不同的浏览器设置不同的编码(IE,谷歌解决方式一致)

    这里是文件下载的页面

    package com.zzx.down;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.URLEncoder;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import sun.misc.BASE64Encoder;
    
    import com.sun.xml.internal.messaging.saaj.util.Base64;
    /*
     * 这个页面是实现文件的下载
     */
    public class DownServlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
                //0,得到文件的路径
            String path = getServletContext().getRealPath("/down/图片.jpg");
                //得到文件名
                //这里寻找"/"要注意使用"\"才能正确的截取
            String filename = path.substring(path.lastIndexOf("\")+1);
            //得到请求的浏览器类型
            String agent = request.getHeader("User-Agent");
            //判断浏览器类型
            System.out.println(agent);
            if(agent.contains("Firefox")){
                //如果是火狐,进行base64编码
                filename = "=?UTF-8?B?"+new BASE64Encoder().encode(filename.getBytes("utf-8")) + "?=";
            }else{
                //url编码,谷歌,IE都可以通过这样设置
                filename=URLEncoder.encode(filename, "UTF-8");
            }
                //1,设置文件的mime类型
                //先得到文件的mime类型
            String type = getServletContext().getMimeType(filename);
                //设置
            response.setContentType(type);
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
               //得到输入流
            InputStream is = new FileInputStream(path);
               //得到输出流
            OutputStream os = response.getOutputStream();
               //2,流对接
            int a=0;
            byte[]arr =new byte[1024*8];
            while((a = is.read(arr))!=-1){
                os.write(arr,0,a);
            }
            //3,关流
            os.close();    //会自动关闭,不过要养成关流的习惯
            is.close();
            
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            doGet(request, response);
        }
    
    }
  • 相关阅读:
    BZOJ5212 ZJOI2018历史(LCT)
    BZOJ5127 数据校验
    253. Meeting Rooms II
    311. Sparse Matrix Multiplication
    254. Factor Combinations
    250. Count Univalue Subtrees
    259. 3Sum Smaller
    156. Binary Tree Upside Down
    360. Sort Transformed Array
    348. Design Tic-Tac-Toe
  • 原文地址:https://www.cnblogs.com/adventurer/p/5496040.html
Copyright © 2011-2022 走看看