SpringMVC实现文件上传和下载

本文详细介绍了如何在SpringMVC中实现文件上传和下载。首先,讲解了文件上传的准备工作,包括配置MultipartResolver和前端表单设置。接着,阐述了SpringMVC如何利用CommonsMultipartFile进行文件上传,包括多种保存上传文件的方法。最后,讨论了文件下载的实现,包括设置响应头和处理输入输出流。通过示例代码和步骤,读者可以轻松掌握这两个功能的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

准备工作

文件上传是项目开发中最常见的功能之一 ,springMVC 可以很好的支持文件上传,但是SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。如果想使用Spring的文件上传功能,则需要在上下文中配置MultipartResolver。

前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器

表单中的enctype属性详细说明:

在这里插入图片描述

  1. application/x-www=form-urlencoded:默认方式,只处理表单域中的 value 属性值,采用这种编码方式的表单会将表单域中的值处理成 URL 编码方式

  2. multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码

  3. text/plain:除了把空格转换为 “+” 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件

文件上传

  1. 编写一个页面进行上传文件操作
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>upload</title>
</head>
<body>
    <form action="${pageContext.request.contextPath}/upload1" method="post" enctype="multipart/form-data">
        <input type="file" name="file">
        <input type="submit">
    </form>
</body>
</html>

一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对于文件上传的处理则涉及在服务器端解析原始的HTTP响应

  • Servlet3.0规范已经提供方法来处理文件上传,但这种上传需要在Servlet中完成,而Spring MVC则提供了更简单的封装。
  • Spring MVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolver实现的。
  • Spring MVC使用Apache Commons FileUpload技术实现了一个MultipartResolver实现类CommonsMultipartResolver。因此,SpringMVC的文件上传还需要依赖Apache Commons FileUpload的组件
  1. 导入文件上传的jar包(依赖),commons-fileupload
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>3.0-alpha-1</version>
        </dependency>
        <!--文件上传下载-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
  1. 配置multipartResolverbean交给Spring来管理

注意bean的id必须为multipartResolver,因为spring会调用这个bean的名字multipartResolver,否则会包上传文件400错误

    <!--注册文件上传配置交给Spring管理-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
        <property name="defaultEncoding" value="utf-8"/>
        <!-- 上传文件大小上限,单位为字节(10485760=10M) -->
        <property name="maxUploadSize" value="10485760"/>
<!--        设置最大内存大小-->
        <property name="maxInMemorySize" value="40960"/>
    </bean>
  1. 编写Controller类进行接收上传的文件并储存写入目录文件中

CommonsMultipartFile的常用方法:

  • String getOriginalFilename():获取上传文件的原名
  • InputStream getInputStream():获取文件流
  • void transferTo(File dest):将上传文件保存到一个目录文件中

方式一:上传文件原生的IO流处理

@PostMapping("/upload")
    //@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile对象
    public String upload(@RequestParam("file")CommonsMultipartFile file, HttpServletRequest request) throws IOException {
        //获取文件名 : file.getOriginalFilename();
        String uploadFileName = file.getOriginalFilename();
        //如果上传文件名为""则重定向到上传文件页面
        if ("".equals(uploadFileName)){
            return "redirect:/index.jsp";
        }
        //设置上传文件保存在当前服务器的目录
        //设置一个当前项目下的/upload目录下的字符串路径
        String realPath = request.getRealPath("/upload");
        //将该字符串路径变为一个文件File对象
        File f = new File(realPath);
        //如果文件路径目录不存在则创建
        if (!f.exists()){
            f.mkdir();
        }
        //创建文件输入流
        InputStream inputStream = file.getInputStream();
        //创建文件输出流对象,传入文件将/upload做为目录,文件名为该上传文件的文件名
        FileOutputStream fileOutputStream = new FileOutputStream(new File(realPath,uploadFileName));
        //创建一个byte数组用来接收上传文件的字节
        byte[] bytes=new byte[1024];
        //如果读取的文件字节不等于-1
        while (inputStream.read(bytes)!=-1){
            //则将读取的文件字节写出到目录下的文件对象
            fileOutputStream.write(bytes);
            //刷新文件输出流缓存
            fileOutputStream.flush();
        }
        //关闭流
        inputStream.close();
        fileOutputStream.close();
        //响应给浏览器
        return "ok";
    }

方式二:采用file.Transto 来保存上传的文件

@PostMapping("/upload1")
    //@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile对象
    public String upload1(@RequestParam("file")CommonsMultipartFile file,HttpServletRequest request) throws IOException {
        //获取文件名(包括后缀名) : file.getOriginalFilename();
        String uploadFileName = file.getOriginalFilename();
        //设置一个当前项目下的/upload目录下的字符串路径
        String realPath = request.getRealPath("/upload");
        //如果上传文件名为""则重定向到上传文件页面
        if ("".equals(uploadFileName)){
            return "redirect:/index.jsp";
        }
        //将该字符串路径变为一个文件File对象
        File f = new File(realPath);
        //如果文件路径目录不存在则创建
        if (!f.exists()){
            f.mkdir();
        }
        //通过CommonsMultipartFile的transferTo方法直接写文件(将文件的全路径和文件名拼接)
        file.transferTo(new File(realPath+"/"+uploadFileName));
        //响应给浏览器
        return "ok";
    }

方式三:采用批量上传文件

  1. 前端上传页面需要在input标签内设置一个可以允许多个文件上传的属性multiple
<form action="${pageContext.request.contextPath}/upload2" method="post" enctype="multipart/form-data">
    <input type="file" multiple="multiple" name="files">
    <input type="submit">
</form>
  1. 编写Controller类,接收的文件类型的参数需要是CommonsMultipartFile[]数组类型
    @PostMapping("/upload2")
    //@RequestParam("files") 将name=files控件得到的批量文件封装成CommonsMultipartFile[]数组对象
    public String upload2(@RequestParam("files")CommonsMultipartFile[] files,HttpServletRequest request) throws IOException {
        //设置一个当前项目下的/upload目录下的字符串路径
        String realPath = request.getRealPath("/upload");
        //将该字符串路径变为一个文件File对象
        File file = new File(realPath);
        //如果文件路径目录不存在则创建
        if (file.exists()){
            file.mkdir();
        }
        //循环遍历出CommonsMultipartFile[]数组中的CommonsMultipartFile文件对象
        for (int i = 0; i <files.length ; i++) {
            CommonsMultipartFile multipartFile = files[i];
            //获取文件名(包括后缀名) : file.getOriginalFilename();
            String filename = multipartFile.getOriginalFilename();
            //如果上传文件名为""则重定向到上传文件页面
            if ("".equals(filename)){
                return "redirect:/index.jsp";
            }
            //通过CommonsMultipartFile的transferTo方法直接写文件(将文件的全路径和文件名拼接)
            multipartFile.transferTo(new File(realPath+"/"+filename));
        }
        //返回浏览器
        return "ok";
    }

文件下载

  1. 准备好需要下载的文件目录及文件

在这里插入图片描述

  1. 编写Controller类,设置响应头以及读取文件、输入输出流操作、关闭流
   @RequestMapping("/download")
    public String download(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //浏览器下载的图片地址,即服务器要放入资源给浏览器下载
        //获取服务器端要下载的文件目录以及文件
        //文件路径
        String realPath = request.getRealPath("/upload");
        //文件
        String fileName="学习大纲.png";
        //设置response 响应头

        /*一般用于下载文件操作时:
        *空白行的出现原因,jsp代码编译后产生。
        * 就是有jsp生成html文件的时候,html文件内部会出现很多空白行。
        * 下载后的文件内的空白行也是这样产生的, response.reset() 来清除首部的空白行
         */
        response.reset();
        //设置字符编码
        response.setCharacterEncoding("utf-8");
        //设置文件传输以二进制传输数据
        response.setContentType("multipart/form-data");
        //设置响应头
        response.setHeader("Content-Disposition",
                "attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));
        //创建文件输入流(传入当前服务器端文件全路径对象)
        FileInputStream fis=new FileInputStream(new File(realPath,fileName));
        //获取输出流对象
        OutputStream outputStream = response.getOutputStream();
        //创建一个byte[]字节数组
        byte[] bytes=new byte[1024];
        int index=0;
        //如果读取的字节不等于-1
        while ((index = fis.read(bytes))!=-1){
            //则写出到浏览器
            outputStream.write(bytes,0,index);
            //清空缓存
            outputStream.flush();
        }
        //关闭流操作
        fis.close();
        outputStream.close();
        //响应浏览器
        return "ok";
    }
  1. 启动Tomcat,测试下载结果

在这里插入图片描述
下载成功后
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值