JAVA EE-文件上传

JAVA EE-文件上传

应该相信,自己是生活的战胜者。 —— 雨果

文件下载

首先我们复习一下文件下载的内容

静态下载
public class AServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
            //1 准备工作
                //设置content-type
            response.setContentType(getServletContext().getMimeType("xxx.zip"));
                //添加响应头 content-disposition
            response.setHeader("Content-Disposition", "attachment;filename=apache-tomcat-6.0.35.zip");  
            //2 获得输入流
            InputStream is
              = getServletContext().getResourceAsStream("/WEB-INF/apache-tomcat-6.0.35.zip");
            //3 获得输出流
            OutputStream os = response.getOutputStream();
            //4 两个流对接
            IOUtils.copy(is, os);

    }

}
根据用户的选择来获取下载

JSP文件:

 <body>
    <a href="/day12-download/AServlet" >点击下载</a><br>
    <a href="/day12-download/BServlet?name=apache-tomcat-6.0.35.zip" >apache-tomcat-6.0.35.zip</a><br>
    <a href="/day12-download/BServlet?name=激活软件_v10.0.0.exe" >激活软件_v10.0.0.exe</a><br>
  </body>

业务处理的Servlet

public class BServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //1 获得参数,拿到用户需要下载的文件名称
        String fileName = request.getParameter("name");
        fileName = new String(fileName.getBytes("ISO-8859-1"),"UTF-8");
        //2 准备工作
        //设置content-type
        response.setContentType(getServletContext().getMimeType(fileName));
            //添加响应头 content-disposition
        response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8")); 
        //2 获得输入流
        InputStream is
          = getServletContext().getResourceAsStream("/WEB-INF/"+fileName);
        //3 获得输出流
        OutputStream os = response.getOutputStream();
        //4 两个流对接
        IOUtils.copy(is, os);
        //关闭输出流
        is.close();
        os.close();
    }

}

下载的乱码问题

客户端的超连接中如果包含了中文,会出现get请求方式乱码问题

            <a href="${pageContext.request.contextPath}/download?filename=天空.mp3">下载王非天空.mp3</a>
                    String filename = request.getParameter("name"); // yog.rar / 她说.mp3
                    byte[] b = filename.getBytes("ISO-8859-1");
                    filename = new String(b,"UTF-8");
                    实际上Get提交时包含中文乱码的解决。

如果下载文件名称中出现了中文乱码问题

            <a href="${pageContext.request.contextPath}/download?filename=天空.mp3">下载王非天空.mp3</a>
                    String filename = request.getParameter("name"); // yog.rar / 她说.mp3
                    byte[] b = filename.getBytes("ISO-8859-1");
                    filename = new String(b,"UTF-8");
                    实际上Get提交时包含中文乱码的解决。

文件上传

  • 为什么使用文件上传?

    • 例如社交网站需要提供用户照片.
    • 很多企业内部,商品网站维护时需要上传一些文件
    • 邮箱需要上传附件….
  • 文件上传的操作

    • 请求方式必须是post
    • 需要使用组件
    • 表单必须设置encType=”multipart/form-data”
    • 上传文件的input 中,name属性必须要填写,不然不会上传.

这样一来,通过request对象,获取InputStream,可以将浏览器提交的所有请求正文读取到.

文件上传需要的插件

    commons-fileupload 它是常用的一个文件上传工具

    使用时要导入两个jar包
        commons-fileupload-1.2.1.jar
        commons-io-1.4.jar

一个上传的浏览器端代码

  <body>
    <!-- 
    1.文件上传,表单必须是post提交
    2.文件上传,还需要在表单上加上enctype属性(提交请求正文的类型)
            *application/x-www-form-urlencoded(默认取值,普通提交)
            *multipart/form-data(多段式提交)
    3.  文件上传,使用<input type="file" name="photo" /> 标签,并且必须有name属性
     -->
    <form action="/day12-upload/BServlet"  method="post" encType="multipart/form-data"  > 
        用户名:<input type="text" name="name" /><br>
        个人近照:<input type="file" name="photo" /><br>
        <input type="submit" value="上传"  />
    </form>
  </body>

下面演示如何使用第三方的jar包来优化文件上传处理

public class BServlet extends HttpServlet {
    //使用文件上传工具类(第三方)
    // 导包  => commons-fileupload-1.2.1.jar
    //     => commons-io-1.4.jar

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // 1 创建配置工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();

        //2 根据配置工厂创建解析请求中文件上传内容的解析器
        ServletFileUpload upload = new ServletFileUpload(factory);

        //3 判断当前请求是否是多段式提交
        if(!upload.isMultipartContent(request)){
            //普通表单提交
            throw new RuntimeException("不是多段式提交!");
        }

        try {
        //4 解析request对象
            List<FileItem>  list = upload.parseRequest(request);
            if(list!=null){
                for(FileItem item : list){
                    //判断当前上传段是普通字段,还是文件上传
                    if(!item.isFormField()){//文件上传段
                        String fName = item.getFieldName();

                        InputStream is = item.getInputStream();//获得文件上传段中,文件的流

                        FileOutputStream fos = new FileOutputStream("d://upload/xxx.jpg");

                        IOUtils.copy(is, fos);

                        fos.close();

                    }else{//普通字段段
                        String name = item.getFieldName();
                        String value = item.getString();

                        System.out.println(name+"==>"+value);

                    }

                }
            }

        } catch (FileUploadException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }

}

文件上传段与普通表单段的区别如下
这里写图片描述

fileupload工具类详解

public class CServlet extends HttpServlet {
    //fileupload 工具类使用详解
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    //1 创建配置工厂=> 有参的构造可以 直接设置下面两个配置
        DiskFileItemFactory factory  = new DiskFileItemFactory();
    //1.1 设置文件上传临时目录 => 默认位置 => tomcat/temp
        factory.setRepository(new File("d:/temp"));
    //1.2 设置文件写入硬盘的缓冲区大小=>默认值=>10k
        factory.setSizeThreshold(10240);
    //2 根据配置工厂创建解析器(解析request对象)
        ServletFileUpload upload = new ServletFileUpload(factory);
    //2.1 判断当前请求是否是多段式提交
        upload.isMultipartContent(request);
    //2.2 设置多段中每段 段头 在解析时,使用什么码表解码 => 当段头中出现中文时,一定要调用该方式指定段头码表
        upload.setHeaderEncoding("UTF-8");
    //2.3 设置文件最大上传大小 (单位:字节)
        upload.setSizeMax(1024*1024*10); //单次请求,总上传大小限制  10兆
        upload.setFileSizeMax(1024*1024);// 每个文件上传段,大小限制 1兆
        List<FileItem> list = null;
        try {
            //2.4 解析request,将每个分段中的内容封装到FileItem中
            list = upload.parseRequest(request);
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
        if(list!=null){
            for(FileItem item : list){
            //3.1 item 判断当前分段是否是普通表单段
                    boolean flag = item.isFormField();
                    //普通段
                    //3.2获得 表单提交的键.(input元素,name属性的值)
                    String fname = item.getFieldName();
                    //3.3 返回文件名称
                    String  name = item.getName();
                    //3.4 获得文件上传中的正文
                    //item.getInputStream();
                    //3.5 以字符串形式返回段体中的内容 注意:文件上传段不建议使用该方法. 
                    String content= item.getString();
                    //3.6  删除上传的临时文件
                    item.delete();
                    System.out.println("是否是普通表单提交:"+flag+",表单提交的键:"+fname+",文件名称:"+name+",文件内容:"+content);
            }

        }
    }

}

关于乱码问题的研究
当上传的文件名中有中文时,如果码表不当就会造成乱码问题的产生。

public class DServlet extends HttpServlet {
    //上传文件名称是中文,乱码问题
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 1 创建配置工厂
                DiskFileItemFactory factory = new DiskFileItemFactory();
        //2 根据配置工厂创建解析请求中文件上传内容的解析器
                ServletFileUpload upload = new ServletFileUpload(factory);

            //解决文件名称中文乱码
                upload.setHeaderEncoding("UTF-8");
                //3 判断当前请求是否是多段式提交
                if(!upload.isMultipartContent(request)){
                    //普通表单提交
                    throw new RuntimeException("不是多段式提交!");
                }

                try {
                //4 解析request对象
                    List<FileItem>  list = upload.parseRequest(request);
                    if(list!=null){
                        for(FileItem item : list){
                            //判断当前上传段是普通字段,还是文件上传
                            if(!item.isFormField()){//文件上传段

                                String fileName = item.getName();

                                System.out.println(fileName);
                            }
                        }
                    }

                } catch (FileUploadException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

    }

}

设置上传文件的最大大小

public class FServlet extends HttpServlet {

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 1 创建配置工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();
//2 根据配置工厂创建解析请求中文件上传内容的解析器
        ServletFileUpload upload = new ServletFileUpload(factory);
        //设置文件上传大小限制
        upload.setFileSizeMax(1024);

        try {
            upload.parseRequest(request);
        } catch (FileUploadException e) {
            e.printStackTrace();
            throw new RuntimeException("文件大小不能超过1kb!");
        }
}

}
        可以设置上传文件大小,如果超过设置大小.将会抛出异常(默认没有最大值)
            void setFileSizeMax(long fileSizeMax) 设置单个文件上传大小 
            void  setSizeMax(long sizeMax) 设置总文件上传大小 

如何实现保存的文件名不会重复

public class GServlet extends HttpServlet {
    //如果将文件全部保存 => 保证文件名称不能重复
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // 1 创建配置工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();

        //2 根据配置工厂创建解析请求中文件上传内容的解析器
        ServletFileUpload upload = new ServletFileUpload(factory);

        //3 判断当前请求是否是多段式提交
        if(!upload.isMultipartContent(request)){
            //普通表单提交
            throw new RuntimeException("不是多段式提交!");
        }

        try {
        //4 解析request对象
            List<FileItem>  list = upload.parseRequest(request);
            if(list!=null){
                for(FileItem item : list){
                    //判断当前上传段是普通字段,还是文件上传
                    if(!item.isFormField()){//文件上传段
                        String fName = item.getFieldName();

                        InputStream is = item.getInputStream();//获得文件上传段中,文件的流

                        //保存之前,生成文件名称( 保证永远不重复)
                        //生成随机字符串即可
                        String fileName = UUID.randomUUID().toString();

                        FileOutputStream fos = new FileOutputStream("d:/upload/"+fileName);

                        IOUtils.copy(is, fos);

                        fos.close();

                    }
                }
            }

        } catch (FileUploadException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }



    }

}

如何防止同一个目录之下上传文件数量过多?

public class HServlet extends HttpServlet {
    //如何将上传文件分目录保存
    // 使用登录用户的用户名 来创建不同的文件夹. 每个用户上传的文件就放到自己的文件夹中
    // 按照日期分目录=> d:/upload/2015/08/24/
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // 1 创建配置工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();

        //2 根据配置工厂创建解析请求中文件上传内容的解析器
        ServletFileUpload upload = new ServletFileUpload(factory);

        //3 判断当前请求是否是多段式提交
        if(!upload.isMultipartContent(request)){
            //普通表单提交
            throw new RuntimeException("不是多段式提交!");
        }

        try {
        //4 解析request对象
            List<FileItem>  list = upload.parseRequest(request);
            if(list!=null){
                for(FileItem item : list){
                    //判断当前上传段是普通字段,还是文件上传
                    if(!item.isFormField()){//文件上传段
                        String fName = item.getFieldName();

                        InputStream is = item.getInputStream();//获得文件上传段中,文件的流

                        // 生成日期目录
                        //1 获得当前日期=>目录结构 的 路径
                        SimpleDateFormat format = new SimpleDateFormat("/yyyy/MM/dd/");
                        String datepath = format.format( new Date()); //    /2015/08/24/
                        //拼接完整保存目录路径
                        String wholePath = "d:/upload"+datepath;// d:/upload/2015/08/24/

                        //确保文件夹存在
                        File directory = new File(wholePath);
                        if(!directory.exists()){//如果文件夹结构不存在
                            directory.mkdirs(); //创建文件夹结构
                        }

                        //保存之前,生成文件名称( 保证永远不重复)
                        //生成随机字符串即可
                        String fileName = UUID.randomUUID().toString();

                        FileOutputStream fos = new FileOutputStream(wholePath+fileName);

                        IOUtils.copy(is, fos);

                        fos.close();

                    }
                }
            }

        } catch (FileUploadException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }



    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值