上传下载

WEB上传下载

一、上传

1.1上传的要求

  • 上传在form标签完成
  • 必须为post请求(get请求有大小有限制)
  • form标签中的encType属性必须为multipart/form-data值
  • input的类型type=file表示要上传的文件
  • 编写服务器接收,处理上传的文件与表单数据

encType=multipart/form-data 表示提交的数据,以多段(每一个表单项表示一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器

1.2 HTTP协议说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wopKmKhE-1584724453903)(C:\Users\333\AppData\Roaming\Typora\typora-user-images\1584718431633.png)]

1.3 文件上传

导入commons-fileupload.jar与commons-io.jar

常用类:

  • ServletFileUpload:解析上传的数据

    • static boolean isMultipartContent(HttpServletRequest request):判断当前上传的数据格式是否为多段的格式
    • List < FileItem > parseRequest((HttpServletRequest request):解析上传的数据,返回一个LIst集合代表form表单的所有项
  • FileItem:代表每一个表单项

    • boolean isFormField():判断当前这个表单项,是否是普通的表单项。还是上传的文件类型,true 表示普通类型的表单项
    • String getFieldName():获取表单项的 name 属性值
    • String getString():获取当前表单项的value值
    • String getString(String encoding):获取当前表单项的value值并设置其字符编码
    • String getName():获取上传的文件名
    • void write(File file):将上传的文件写出到硬盘

前台页面

<form action="${pageContext.request.contextPath}/upload" method="post"
      enctype="multipart/form-data">
    用户名:<input name="name" > <br>
    上传文件:<input type="file" name="fileName">
    <input type="submit">
  </form>

服务器

	protected void doPost(HttpServletRequest request, HttpServletResponse response) {
       	//设置请求、响应的编码
       	request.setCharacterEncoding("utf-8");
      	response.setCharacterEncoding("utf-8");
        //断当前上传的数据格式是否为多段的格式
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        if (!isMultipart){
            System.out.println("上传格式不是Multipart");
            return ;
        }
        FileItemFactory fileItemFactory = new DiskFileItemFactory();
        //创建ServletFileUpload对象,需要FileItemFactory对象
        ServletFileUpload upload = new ServletFileUpload(fileItemFactory);
        List list = null ;
        try {
            //解析上传的数据,得到form表单的所有项
            list = upload.parseRequest(request);
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
        //使用迭代器遍历
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            //强转为FileItem类型
            FileItem fileItem = (FileItem)iterator.next();
            //判断是否为普通的表单项
            if (fileItem.isFormField()){
                String fieldName = fileItem.getFieldName();
                String value = fileItem.getString("utf-8");
                System.out.println(fieldName+"=="+value);
            }else {//为文件类型
                //获取文件名称
                String fileName = fileItem.getName();
                //截取文件类型
                fileName = fileName.substring(fileName.lastIndexOf('.'));
                try {
                    //将上传的文件写出到硬盘
                    fileItem.write(new File("F:\\"+randomName()+fileName));
                    //删除内存中的临时文件
                    fileItem.delete();
            fileItem.delete();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }

    }

	//随机生成5为数的String类型
    private static String randomName(){
        int i = (int)(Math.random()*89999)+10000;
        String str = i+"";
        return str ;
    }

二、下载

2.1步骤

  • 下载的文件路径
  • 下载的文件的文件名
  • 设置浏览器能支持下载的操作(设置响应头)
  • 读入下载的文件
  • 写出下载的文件
  • 关闭资源

设置响应头

  • response.setHeader(“Content-Disposition”, “attachment; fileName=文件名”);
  • 这个响应头告诉浏览器。这是需要下载的
  • attachment 表示附件
  • fileName=文件名, 表示下载的文件名

如果下载的文件是中文名的话,下载无法正确显示出正确的中文名。原因是在响应头中,不能包含有中文字符,只能包含 ASCII 码。

因此需要设置字符编码

	protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        //1、需要下载的文件路径
        String path = "D:\\BaiduNetdiskDownload\\java web\\资料\\10-项目第三阶段\\笔记\\文件上传和下载\\ASCII码表I.jpg";
        //2、下载的文件的文件名
        String fileName = path.substring(path.lastIndexOf("\\")+1);
        //3、设置浏览器能支持下载的操作(设置响应头) -- URLEncoder.encoder("文件名","字符集")设置中文编码
        try {
            response.setHeader("Content-Disposition","attachment;fileName="+URLEncoder.encode(fileName,"utf-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        InputStream in = null;
        OutputStream out = null;
        try {
            //4、读入下载的文件
            in = new FileInputStream(path);
            out = response.getOutputStream();
            
            //5、设置缓冲区
            byte[] buffer = new byte[1024] ;
            int reader = 0 ;
            
            //6、写出下载的文件
            while((reader=in.read(buffer))!=-1){
                out.write(buffer,0,reader);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //7、关闭IO流
            if (out!=null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (in!=null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

2.2 中文乱码问题

1、IE和谷歌浏览器

浏览器是 IE 浏览器 或者 是谷歌浏览器,要使用 URLEncoder 类先对中文名进行 UTF-8 的编码操作

String str = "attachment: fileName=" + URLEncoder.encode("中文.txt","UTF-8");
response.setHeader("Content-Disposition",str);
2、火狐浏览器

浏览器是火狐浏览器。 需要对中文名进行 BASE64 的编码操作

filename = “=?charset?B?xxxxx?=” 含义

  • “=?” 表示编码的开始
  • “charset” 表示字符集
  • B 表示BASE64编码
  • “xxxx” 表示编码的内容(BASE64编码的文件名)
  • “?=” 表示编码内容的结束
		//使用BASE64 编码后的文件名
		String nameEncoding = new BASE64Encoder().encode("文件名".getBytes("UTF-8"));
		String str = "attachment;fileName=" + "=?utf-8?B?" + nameEncoding + "?=";
		//设置到响应头中
        resp.setHeader("Content-Disposition",str);

码后的文件名
String nameEncoding = new BASE64Encoder().encode(“文件名”.getBytes(“UTF-8”));
String str = “attachment;fileName=” + “=?utf-8?B?” + nameEncoding + “?=”;
//设置到响应头中
resp.setHeader(“Content-Disposition”,str);


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值