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);
        }
    
    }
  • 相关阅读:
    Java正则表达式入门
    StringBuffer ,String,StringBuilder的区别
    JAVA的StringBuffer类
    容器vector的使用总结 容器stack(栈)
    c++网络通信(与服务器通信聊天)和c#网络通信
    C#与SQLite数据库
    我的vim配置文件
    在world中批量调整图片的大小
    C#判断文件及文件夹是否存在并创建(C#判断文件夹存在)
    C# Thread类的应用
  • 原文地址:https://www.cnblogs.com/adventurer/p/5496040.html
Copyright © 2011-2022 走看看