文件上传下载(JavaWeb - SpringMVC - SpringBoot)

目录

1. 文章说明

2. JavaWeb实现文件上传下载

2.1 JavaWeb实现文件上传的步骤

2.2 JavaWeb实现文件上传代码

2.3 文件上传的HTTP协议说明

2.4 JavaWeb实现文件下载

 3. SpringMVC实现文件上传下载

3.1 SpringMVC实现文件上传的步骤


1. 文章说明

文件上传在Web项目开发中是一个很重要的功能点,随着技术(框架)的更新变化,不同的技术对文件上传有不同的实现方式。在上传和下载文件的使用操作上,新的技术比旧的技术实现了更便捷(更容易上手)操作方式,这是因为新技术对旧技术进行了更深层次的封装,屏蔽了底层的一些实现细节,但是这也导致我们在使用新技术的时候,大多数时候只是停留在会使用的层面,而不明白这些技术的演变过程和底层实现原理,本篇文章就从传统的JavaWeb 到 SpringMVC 再到SpringBoot实现文件上传的方式做一个总结。

2. JavaWeb实现文件上传下载

2.1 JavaWeb实现文件上传的步骤

  1. 引入可以实现文件上传的两个jar包 commons-fileupload-1.2.1.jar 和 commons-io-1.4.jar
  2. 写一个如下要求的form表单
    • 表单提交方式必须为post
    • form标签的enctype属性值必须为multipart/form-data 【enctype=multipart/form-data表示提交的数据以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器,因为客户端是以流的形式把信息发送给服务器段,所以在服务器段接收的时候,也需要以流的形式进行接收】
    • form表单中使用 input="file"添加要上传的文件
    • 编写服务器代码(Servlet程序)接收并处理上传的数据

2.2 JavaWeb实现文件上传代码

  1. file_upload.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件上传</title>
</head>
<body>
    <form action="http://localhost:8080/book/uploadServlet" 
          enctype="multipart/form-data" method="post">
        用户名:<input type="text" name="username"><br/>
        头  像:<input type="file" name="photo"><br/>
              <input type="submit" value="提交">
    </form>
</body>
</body>
</html>

2. UploadServlet.java

package com.example.web;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;

public class UploadServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 判断上传的数据是否为多段数据
        if(ServletFileUpload.isMultipartContent(req)){
            // 2. 创建FileItemFactory工厂实现类
            FileItemFactory fileItemFactory = new DiskFileItemFactory();
            // 3. 创建用于解析上传数据的工具类ServletFileUpload类
            ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
            try {
                // 4. 解析上传的数据,得到每一个表单项FileItem
                List<FileItem> fileItems = servletFileUpload.parseRequest(req);
                // 5. 循环判断每一个表单项,是普通表单项还是文件表单项
                for (FileItem fileItem : fileItems) {
                    if(fileItem.isFormField()){
                        // 普通表单项
                        System.out.println("表单项的name值:"+fileItem.getFieldName());
                        System.out.println("表单项的value值:"+fileItem.getString("UTF-8"));
                    }else {
                        // 文件表单项
                        System.out.println("表单项的name值:"+fileItem.getFieldName());
                        System.out.println("上传的文件名:"+fileItem.getName());
                        // 保存文件到服务器指定路径下
                        fileItem.write(new File("D:\\"+fileItem.getName()));
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

2.3 文件上传的HTTP协议说明

        说明:图中 “上传的文件的数据” 并没有显示出要上传的文件数据,是因为浏览器检测到是二进制流的文件数据,就不再展示在此处了(Chrome浏览器不展示,FireFox浏览器会展示上传的文件的二进制流数据)

2.4 JavaWeb实现文件下载

1. DownloadFileServlet

package com.example.web;

import org.apache.commons.io.IOUtils;
import sun.misc.BASE64Encoder;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;

public class DownloadFileServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1、获取要下载的文件名(此处为了演示方便,写死在代码中)
        String downloadFileName = "3.jpg";

        //2、读取要下载的文件内容 (通过ServletContext对象可以读取)
        ServletContext servletContext = getServletContext();

        //3、获取要下载的文件类型
        String mimeType = servletContext.getMimeType("/pages/file/" + downloadFileName);
        System.out.println("下载的文件类型:" + mimeType);

        //4、在回传前,通过响应头告诉客户端返回的数据类型
        resp.setContentType(mimeType);

        //5、还要告诉客户端收到的数据是用于下载使用(还是使用响应头来告诉客户端)
        // Content-Disposition响应头,表示收到的数据怎么处理
        // attachment表示附件,表示下载使用
        // filename= 表示指定下载的文件名
        // url编码是把汉字转换成为%xx%xx的格式
        if (req.getHeader("User-Agent").contains("Firefox")) {
            // 如果是火狐浏览器使用Base64编码
            resp.setHeader("Content-Disposition", "attachment; filename==?UTF-8?B?" + new BASE64Encoder().encode("中国.jpg".getBytes("UTF-8")) + "?=");
        } else {
            // 如果不是火狐,是IE或谷歌,使用URL编码操作
            resp.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("中国.jpg", "UTF-8"));
        }
        /**
         * /斜杠被服务器解析表示地址为http://ip:prot/工程名/  映射 到代码的Web目录
         */
        InputStream resourceAsStream = servletContext.getResourceAsStream("/pages/file/" + downloadFileName);
        // 获取响应的输出流
        OutputStream outputStream = resp.getOutputStream();
        //3、把下载的文件内容回传给客户端 ,读取输入流中全部的数据,复制给输出流,输出给客户端
        IOUtils.copy(resourceAsStream, outputStream);
    }
}

2. 文件下载的HTTP协议头

  • 火狐浏览器

  •  谷歌浏览器

 3. SpringMVC实现文件上传下载

3.1 SpringMVC实现文件上传的步骤

  • 在pom.xml文件中导入文件上传所需的jar包坐标
           <!--文件上传-->
            <dependency>
                <groupId>commons-fileupload</groupId>
                <artifactId>commons-fileupload</artifactId>
                <version>1.4</version>
            </dependency>
  • 要求form表单提交方式为post,且添加属性enctype=multipartr/form-data
    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>测试文件上传和下载</title>
    </head>
    <body>
    <a th:href="@{/testDown}">通过ResponseEntity下载服务器中的文件到客户端</a><br/>
    <form th:action="@{/testUp}" method="post" enctype="multipart/form-data">
        用户名:<input type="text" name="username"><br/>
        头  像:<input type="file" name="photo"><br>
               <input type="submit" value="上传">
    </form>
    </body>
    </html>
  • SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息,需要在SpringMVC的配置文件中添加如下配置:
    <!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons."></bean>
  • SpringMVC中的控制器方法

     // 文件上传
        @RequestMapping("/testUp")
        public String testUp(MultipartFile photo,HttpSession session,String username) throws IOException {
            // 可以通过控制器方法的形参获取普通表单项的内容
            System.out.println("username = " + username);
    
            //获取上传的文件的文件名
            String fileName = photo.getOriginalFilename();
            System.out.println("fileName = " + fileName);
    
            //处理文件重名问题
            String hzName = fileName.substring(fileName.lastIndexOf("."));
            System.out.println("hzName = " + hzName);
            fileName = UUID.randomUUID() + hzName;
            System.out.println("hzName = " + hzName);
    
            //获取服务器中photo目录的路径
            ServletContext servletContext = session.getServletContext();
            String photoPath = servletContext.getRealPath("photo");
            System.out.println("photoPath = " + photoPath);
            File file = new File(photoPath);
            if(!file.exists()){
                file.mkdir();
            }
            String finalPath = photoPath + File.separator + fileName;
            System.out.println("finalPath = " + finalPath);
            //实现上传功能,需要使用到 commons-fileupload-1.2.1.jar 及其所依赖的 commons-io-1.4.jar
            photo.transferTo(new File(finalPath));
            return "success";
        }
        // 文件下载
        @RequestMapping("/testDown")
        public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
            //获取ServletContext对象
            ServletContext servletContext = session.getServletContext();
            //获取服务器中文件的真实路径
            String realPath = servletContext.getRealPath("/static/img/1.jpg");
            System.out.println("realPath = " + realPath);
            //创建输入流
            InputStream is = new FileInputStream(realPath);
            //创建字节数组
            //byte[] bytes = new byte[is.available()];
            byte[] buffer = new byte[1024];
            int len = 0;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            while ((len = is.read(buffer)) != -1){
                out.write(buffer,0,len);
            }
            byte[] bytes = out.toByteArray();
            //将流读到字节数组中
            //is.read(bytes);
            //创建HttpHeaders对象设置响应头信息
            MultiValueMap<String, String> headers = new HttpHeaders();
            //设置要下载方式以及下载文件的名字
            headers.add("Content-Disposition", "attachment;filename=1.jpg");
            String mimeType = servletContext.getMimeType("/static/img/1.jpg");
            headers.add("Content-Type",mimeType);
            //设置响应状态码
            HttpStatus statusCode = HttpStatus.OK;
            //创建ResponseEntity对象
            ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(bytes, headers, statusCode);
            //关闭输入流
            is.close();
            return responseEntity;
        }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值