zoukankan      html  css  js  c++  java
  • Java实战之04JavaWeb-08文件上传与下载

    一、文件上传

    1.文件上传的实质是什么

    文件的拷贝,文件从客户端拷贝服务器端

    2.文件上传的工作

    (1)客户端怎样将本地文件输出去?

    1)文件上传的表单项 <input type=”file”>表单项必须有name属性值

    2)文件上传必须是post提交方式

    3)表单项中添加一个属性 enctype=“multipart/form-data”

    (2)服务器怎样接受上传的文件,并将文件保存到服务器上?

    注意:如果表单的enctype是multipart/form-data,那么通过request.getParameter等类似的方法都失效。虽然方法失效,但是request对象中仍然封装请求的数据。

    获取多部分表单数据原理:

    使用工具完成上文件文件表单项数据接收

    Apache-Commons-fileupload工具可以很方便完成上传文件的接受工作

    使用file-upload工具需要到两个jar

    fileupload中常用API

    磁盘文件项工厂:DiskFileItemFactory:设置文件上传一些参数

    文件上传的核心类:ServletFileUpload:文件上传的核心类

    文件项对象:FileItem:代表上传文件的表单中的每一部分

    API进行详解

     1         try {
     2             //1、创建磁盘文件项工厂
     3             DiskFileItemFactory factory = new DiskFileItemFactory();
     4             //2、创建文件上传的核心类
     5             ServletFileUpload upload = new ServletFileUpload(factory);
     6             //3、解析request获得表单项FileItem
     7             List<FileItem> parseRequest = upload.parseRequest(request);
     8             //4、判断是普通表单项还是文件上传项
     9             for(FileItem item:parseRequest){
    10                 //判读普通表单项还是文件上传项
    11                 boolean formField = item.isFormField();//判断是否是普通表单 true是普通表单
    12                 if(formField){
    13                     //普通表单
    14                     //获得表单项的name属性值
    15                     String fieldName = item.getFieldName();
    16                     //获得表单项的value值
    17                     String value = item.getString("UTF-8");
    18                     
    19                     System.out.println(fieldName+"----"+value);
    20                 }else{
    21                     //文件上传项
    22                     //获得上传文件的名称
    23                     String fileName = item.getName();
    24                     //获得上传文件的内容
    25                     InputStream in = item.getInputStream();
    26                     //写到服务器端的磁盘上
    27                     //C:\Users\haohao\Desktop\apache-tomcat-7.0.53\webapps\day20_208\upload
    28                     String path = this.getServletContext().getRealPath("/upload");
    29                     //C:\Users\haohao\Desktop\apache-tomcat-7.0.53\webapps\day20_208\upload\itcast.txt
    30                     OutputStream out = new FileOutputStream(path+"/"+fileName);
    31                     //文件拷贝的模板代码
    32                     int len = 0;
    33                     byte[] buffer = new byte[1024];
    34                     while((len=in.read(buffer))>0){
    35                         out.write(buffer, 0, len);
    36                     }
    37                     in.close();
    38                     out.close();
    39                 }
    40             }
    41         } catch (FileUploadException e) {
    42             e.printStackTrace();
    43         }

    (3)文件上传的细节

    1)文件在上传时 会根据浏览器不同导致上传的文件的名称是不同

    服务器端在item.getName() 获得上传文件的名称时会如下两种情况

    有磁盘符 C:abcxxx.txt

    没有磁盘符 xxx.txt

    2)解决上传文件的重名的问题

    解决方案:将上传文件的名称替换成随机uuid

    例如:美女.jpg-----uuid.jpg

    3)上传文件过多的问题

    目录怎样去划分?

    时间划分目录

    区域划分目录

    类型划分目录

    按照算法进行目录划分

    根据文件的hashcode

    二、文件下载

    1.文件下载实质

    文件的拷贝,从服务器的磁盘上将文件拷贝本地客户端

    2.文件下载的工作

    (1)服务器端怎样将文件发送出去?

    response.getOutputStream().write();

    (2)客户端怎样接受服务器端传输的文件?

    下载文件的过程是浏览器内核控制,不需要编码

    3.问题:

    文件什么情况下可以下载?

    浏览器不识别文件都下载,识别的文件进行解析

    什么情况下需要编写文件下载的代码?

    浏览器可以识别的文件编写文件下载的代码

    4.怎样在服务器端编写文件下载代码

    步骤:

    1)读取服务器磁盘上的文件

    2)创建输出流写给客户端 response.getOutputStream()

    3)告知客户端这个文件不需要解析 需要下载

    Content-Type:文件类型MIME类型

    获得MIME类型:getServletContext().getMimtType(文件名);

    Content-Disposition:attachment;filename=文件名称

    5.关于下载中文文件

    发现中文文件在下载时不能正常显示文件名称

    问题出现在 attachment;filename=中文文件名称

    怎样对要下载的中文名称进行编码?

    if(火狐){

    对下载中文文件名使用base64编码

    }else if(ie){

    对下载中文文件名使用UTF-8编码

    }

     1         //获取filename
     2         String filename = request.getParameter("filename");//????
     3         //解决get提交的中文乱码问题
     4         filename = new String(filename.getBytes("iso8859-1"),"UTF-8");//美女.jpg
     5         
     6         String downloadFilename = filename;
     7         String agent = request.getHeader("User-Agent");
     8         if (agent.contains("MSIE")) {
     9             // IE浏览器
    10             downloadFilename = URLEncoder.encode(filename, "utf-8");
    11             downloadFilename = filename.replace("+", " ");
    12         } else if (agent.contains("Firefox")) {
    13             // 火狐浏览器
    14             BASE64Encoder base64Encoder = new BASE64Encoder();
    15             downloadFilename = "=?utf-8?B?"
    16                     + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
    17         } else {
    18             // 其它浏览器
    19             downloadFilename = URLEncoder.encode(filename, "utf-8");
    20             
    21         }
    22         
    23         //response.setHeader("Content-Disposition","attachment;filename=" + new String(filename.getBytes("gbk"), "ISO8859-1"));
    24 
    25 
    26         //设置两个头通知客户端要进行文件的下载
    27         response.setContentType(this.getServletContext().getMimeType(filename));
    28         response.setHeader("Content-Disposition", "attachment;filename="+downloadFilename);//问题:给客户端的filename乱码
    29 
    30         //编写文件下载的代码
    31         String path = this.getServletContext().getRealPath("/download/"+filename);
    32         InputStream in = new FileInputStream(path);
    33         OutputStream out = response.getOutputStream();
    34         int len = 0;
    35         byte[] buffer = new byte[1024];
    36         while((len=in.read(buffer))>0){
    37             out.write(buffer, 0, len);
    38         }
    39         in.close();
    40     }

    不同浏览器默认对下载文件名称解码方式不同,导致客户端在编码时要进行判断

    火狐是什么解码方式:base64

    ie是什么解码方式:UTF-8

  • 相关阅读:
    u-boot 2011.09 调用kernel 的流程
    Delphi repeat Until 运用
    clientdataset的使用
    类型TTreeView.items.add 与 TTreeView.items.addchild有何区别?(10分)
    delphi中nil、null、UnAssigned区别
    操作TreeView(咏南工作室)
    delphi7 treeview + 数据库 实现动态节点维护
    Delphi Try Except 实例
    Delphi 中自定义异常及异常处理的一般方法
    Delphi中的异常处理(10种异常来源、处理、精确处理)
  • 原文地址:https://www.cnblogs.com/minihouseCoder/p/5632124.html
Copyright © 2011-2022 走看看