BS模式文件的上传和下载

1 文件上传

1.1 文件的上传步骤

1,需要一个form标签,method=post
	(采用post的方式是因为get的长度有限)

2,form标签的enctype属性的值必须是 multipart/form-data
	(代表上传的数据以多段的形式拼接,然后以二进制流的形式发送到服务器)

3,form标签内需要一个<input type="file">来选择需要上传的文件

4,在服务器端接收二进制流并处理

1.2 文件上传时的HTTP协议内容

页面中的上传文件表单:

<form action="/MyServlet2" method="post" enctype="multipart/form-data">
    用户名 <input type="text" name="userName"> <br>
    头 像  <input type="file" name="photo"> <br>
    <input type="submit" value="上传">
</form> <br>

上传表单的使用:
在这里插入图片描述
提交后在Chrome浏览器中的HTTP协议内容:

		POST /MyServlet1 HTTP/1.1
        Host: localhost:8080
        Connection: keep-alive
        Content-Length: 293
        Cache-Control: max-age=0
        sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"
        sec-ch-ua-mobile: ?0
        Upgrade-Insecure-Requests: 1
        Origin: http://localhost:8080
        
        Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryBpBL5EuHkTg5qb4m
        // 表示提交的数据类型 multipart/form-data表示提交的数据以多段的形式进行拼接,然后以二进制流的形式发送给服务器
        // boundary表示每段数据的分隔符,----WebKitFormBoundaryBpBL5EuHkTg5qb4m由浏览器随机生成,是数据的分隔符

        User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36
        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
        Sec-Fetch-Site: same-origin
        Sec-Fetch-Mode: navigate
        Sec-Fetch-User: ?1
        Sec-Fetch-Dest: document
        Referer: http://localhost:8080/
        Accept-Encoding: gzip, deflate, br
        Accept-Language: zh-CN,zh;q=0.9
        Cookie: Idea-ce0ce528=48e61e25-191c-4d62-8bfb-19417bc25f46; JSESSIONID=28C7E0C3069342202B9033E9B469C1F9

        // 每两个分隔符之间就是表单中的一个表单项
        ------WebKitFormBoundaryBpBL5EuHkTg5qb4m
        Content-Disposition: form-data; name="userName"

        Coisini
        ------WebKitFormBoundaryBpBL5EuHkTg5qb4m
        Content-Disposition: form-data; name="photo"; filename=""
        Content-Type: application/octet-stream

		// 这里是文件的内容但是过长被Chrome省略
        ------WebKitFormBoundaryBpBL5EuHkTg5qb4m--

当提交数据后,表单中的内容将会被分段并转化为二进制流传输到服务器,服务器接收到的二进制流就是表单中的内容(包括普通表单项和上传文件表单项)

接下来需要对这串二进制流进行处理:

1,将二进制流转换为表单项数据

2,将普通表单项和上传文件表单项分类处理

3,将上传文件表单项中的文件写入服务器的磁盘

1.3 解析上传的流

解析这个二进制流,可以采用commons-fileupload.jar和commons-io.jar来完成,这两个jar文件内提供了现成的工具

jar文件的Maven依赖:

		<dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>

对二进制流的处理需要在一个Servlet程序内的doPost方法内进行:

	@Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        /*
        * 首先判断本次请求是否是多段数据请求
        * 如果是则说明本次请求中会上传文件,需要处理二进制流
        * 不是则说明本次请求处理一个普通的表单
        * */
        if(ServletFileUpload.isMultipartContent(request)) {
            /*处理带文件的二进制流*/

            // 1,创建用于解析二进制流的ServletFileUpload对象
            FileItemFactory fileItemFactory = new DiskFileItemFactory();
            ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);

            try {
                // 2,解析二进制流获得一个表单项对象列表
                List<FileItem> fileItems = servletFileUpload.parseRequest(request);

                // 3,将表单项对象列表分类,分成普通表单项和上传文件表单项分类处理
                for(FileItem fileItem : fileItems) {
                    // 处理普通表单项
                    if(fileItem.isFormField()) {
                        
                        // 输出该表单项的name属性
                        System.out.println(fileItem.getFieldName());
                        // 输出该表单项的值 可以解决中文乱码的问题
                        System.out.println(fileItem.getString("UTF-8"));
                        
                        // 处理上传文件表单项
                    } else {
                        
                        // 输出该表单项的name属性
                        System.out.println(fileItem.getFieldName());
                        // 输出文件名
                        System.out.println(fileItem.getName());
                        
                        // 将该文件写到本地磁盘
                        fileItem.write(new File("D:\\" + fileItem.getName()));
                    }
                }

            } catch (Exception e) {}

        } else {
            /*处理普通表单*/
        }

    }

上传文件过程:

1,判断本次请求处理的是普通表单还是带上传文件的表单,普通表单则正常处理

2,创建用于解析表单的ServletFileUpload类对象

3,通过ServletFileUpload类对象解析request对象,获取表单项列表

4,遍历表单项列表,将普通表单项和带上传文件的表单项分开处理

5,将带上传文件的表单项通过FileItem.write(new File("路径"))写入本地磁盘

2 文件下载

2.1 下载文件的步骤

服务器端:
1,获取表单中的想要下载的文件的文件名

2,获取ServletContext对象,根据文件名获得该文件的输入流

3,通过response对象获取响应输出流

4,更改响应头,告知客户端下载文件的数据类型(MIME格式)

5,更改响应头,告知客户端收到的数据是从服务器下载的文件

6,将文件输入流中的内容写入响应输出流,完成下载

2.2 下载文件

在客户端下载表单中输入想要下载的文件:
在这里插入图片描述
服务器端的处理:

	@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1,获取客户端想要下载的文件名
        String downloadFileName = request.getParameter("fileName");

        // 2,获取ServletContext对象,并取得目标文件的输入流
        ServletContext servletContext = getServletContext();
        InputStream inputStream = servletContext.getResourceAsStream("/file/" + downloadFileName);

        // 3,通过response对象获取响应流
        OutputStream outputStream = response.getOutputStream();

        // 4,更改响应头,告知客户端返回数据的MIME格式
        String fileType = servletContext.getMimeType("/file/" + downloadFileName);
        response.setContentType(fileType);

        // 5,更改响应头,告知客户端本次响应收到的数据是从服务器下载的文件
        response.setHeader("Content-Disposition", "attachment;filename");
        
        // 6,将文件输入流写入响应输出流,完成下载
        IOUtils.copy(inputStream, outputStream);
    }

在第5步更改响应头,告知客户端本次收到的数据是从服务器下载的文件时:

response.setHeader("Content-Disposition", "attachment;filename");

Content-Disposition	表示接收到的数据怎么处理
attachment;	表示作为下载文件

filename 表示下载文件在客户端显示的文件名称
filename默认为服务器端下载文件的文件名,也可以更改filename的值
response.setHeader("Content-Disposition", 
	"attachment;filename=" + URLEncoder.encode("素材.png", "UTF-8"));

但是如果想写成中文的话,在Chrome和IE上需要进行URL编码
在火狐上需要进行Base64编码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值