SpringMVC之文件上传和文件下载

1. 文件上传

在web开发中一般会有文件上传的操作

一般JavaWeb开发中文件上传使用的 Apache组织的Commons FileUpload组件

SpringMVC中使用 MultipartFile file对象接受上传文件,必须保证 后台参数的名称和表单提交的文件的名称一致

文件上传必须条件

  1. 表单必须post
  2. 表单必须有 file 文件域

表单的 enctype="multipart/form-data"

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

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

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

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

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

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

<form action="" enctype="multipart/form-data" method="post">
   <input type="file" name="file"/>
   <input type="submit">
</form>

一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对于文件上传的处理则涉及在服务器端解析原始的HTTP响应。在2003年,Apache Software Foundation发布了开源的Commons FileUpload组件,其很快成为Servlet/JSP程序员上传文件的最佳选择。

  • Servlet3.0规范已经提供方法来处理文件上传,但这种上传需要在Servlet中完成。

  • 而Spring MVC则提供了更简单的封装。

  • Spring MVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolver实现的。

  • Spring MVC使用Apache Commons FileUpload技术实现了一个MultipartResolver实现类:

  • CommonsMultipartResolver。因此,SpringMVC的文件上传还需要依赖Apache Commons FileUpload的组件

1.1. 拷贝jar包

1.2. 准备jsp页面

<fieldset>
        <legend>单个文件上传</legend>
        <form action="${pageContext.request.contextPath}/upload.do" method="post"             
                       enctype="multipart/form-data">

            姓名: <input name="username"><br>
            头像: <input type="file" name="headImg"><br>
            <button type="submit">提交</button>
        </form>
</fieldset>

1.3. 后台代码

SpringMVC中使用  MultipartFile file对象接受上传文件,必须保证 后台方法MultipartFile 参数的名称和表单提交的文件的名称一致

//SpringMVC中使用  MultipartFile file对象接受上传文件,必须保证 后台参数的名称和表单提交的文件的名称一致
    @RequestMapping("/upload")
    public String singleUpload(MultipartFile headImg,@RequestParam("username")String username) throws IOException {

        System.out.println(headImg.getName());//获取上传文件的表单名称
        System.out.println(headImg.getContentType());//MIME类型
        System.out.println(headImg.getSize());//文件大小
        System.out.println(headImg.getOriginalFilename());//获取上传文件的完整名称
        //获取上传文件对应的输入流
        //InputStream in = headImg.getInputStream();

        //创建一个磁盘目录用于保存文件
        File destFile= new File("c:/upload");
        if(!destFile.exists()) {
            destFile.mkdir();
        }
        //使用uuid作为文件随机名称
        String fileName = UUID.randomUUID().toString().replaceAll("-", "");
        //使用FileNameUtils获取上传文件名的后缀
        String extension = FilenameUtils.getExtension(headImg.getOriginalFilename());// jpg , png 等等
        //创建新的文件名称
        String newFileName = fileName + "."+extension;

        //创建要保存文件的File对象
        File file = new File(destFile, newFileName);
        //保存文件到本地磁盘
        headImg.transferTo(file);

        return "redirect:/upload.jsp";
    }

1.4. 配置文件上传解析器

配置文件上传解析器:bean的名字是固定的
使用spring表达式 #{1024*1024}

<!-- 配置文件上传解析器:bean的名字是固定的,底层使用的名称注入 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 设置上传文件的最大尺寸为1MB -->
    <property name="maxUploadSize" value="#{1024 * 1024}"></property>
</bean>

1.5. 多文件上传

<fieldset>
        <legend>单个文件上传</legend>
        <form action="${pageContext.request.contextPath}/uploads.do" method="post" enctype="multipart/form-data">
            文件1: <input type="file" name="headImgs"><br>
            文件2: <input type="file" name="headImgs"><br>
            文件3: <input type="file" name="headImgs"><br>
            <button type="submit">提交</button>
        </form>
    </fieldset>
@RequestMapping("/uploads")
    public String singleUploads(MultipartFile[] headImgs) throws IOException {


        //创建一个磁盘目录用于保存文件
        File destFile= new File("c:/upload");
        if(!destFile.exists()) {
            destFile.mkdir();
        }
        for (int i = 0; i < headImgs.length; i++) {
            MultipartFile headImg = headImgs[i];

            //使用uuid作为文件随机名称
            String fileName = UUID.randomUUID().toString().replaceAll("-", "");
            //使用FileNameUtils获取上传文件名的后缀
            String extension = FilenameUtils.getExtension(headImg.getOriginalFilename());// jpg , png 等等
            //创建新的文件名称
            String newFileName = fileName + "."+extension;

            //创建要保存文件的File对象
            File file = new File(destFile, newFileName);
            //保存文件到本地磁盘
            try {
                headImg.transferTo(file);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return "redirect:/upload.jsp";
    }

2. 文件下载

文件下载,SpringMVC并没有做过多的封装,还是使用原来的下载方式

package cn.zj.springmvc.controller;

import java.io.FileInputStream;
import java.io.IOException;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class DownloadController {
    /*
     * 下载文件思路
     * 1. 接受需要下载文件名称,根据文件名称,找到磁盘对应的文件,读取到内存中形成一个输入流
     * 2. 将输入流通过响应对象(HttpServletResponse)响应给浏览器(下载)
     *
     * 注意:Web一般只会下载小型文件
     *
     */
    @RequestMapping("/download")
    public void upload(String fileName ,HttpServletResponse response) throws IOException {
        //0. 判断是否vip,有积分,金豆
        //TODO

        //1. 接受文件名,读取磁盘对应的文件,创建输入流对象

        FileInputStream inputStream = new FileInputStream("C:/"+fileName);

        //2.获取响应对象的输出流
        ServletOutputStream outputStream = response.getOutputStream();


        //3.文件下载文件名的编码使用ISO-08859-1编码
        //我们需要将我们UTF-8的 filename转换ISO-8859-1编码
        //3.1先将字符串以UTF-8转换成字节数组
        byte[] bytes = fileName.getBytes("UTF-8");
        //3.2再将字节数组以 ISO-8859-1转换字符串
        fileName = new String(bytes, "ISO-8859-1");


        //4.响应的内容应该是以附件的形式响应给浏览器(设置响应头)
        response.setHeader("Content-Disposition", "attachment;filename="+fileName);

        //5.响应文件给浏览器
        IOUtils.copy(inputStream, outputStream);

    }

}

3. SpringMVC的拦截器

拦截器 : Interceptor

Spring MVC 的拦截器类似于Servlet 开发中的过滤器Filter,用于对Controller进行预处理和后处理。

使用SpringMVC拦截器步骤:

1)定义拦截器类,实现接口 org.springframework.web.servlet.HandlerInterceptor

2)在applicationContext.xml中配置拦截器

拦截器方法的执行时机:

1):preHandle:控制器方法执行之前执行,返回结果为true表示放行,如果返回为false,表示拦截(可以做权限拦截,登录检查拦截).

2):postHandle:控制器方法执行后,视图渲染之前执行(可以加入统一的响应信息).

3):afterCompletion:视图渲染之后执行(处理Controller异常信息,记录操作日志,清理资源等)

3.1. 自定义拦截器

public class CheckLoginInterceptor implements HandlerInterceptor {
    //1):preHandle:控制器方法执行之前执行,返回结果为true表示放行,如果返回为false,表示拦截(可以做权限拦截,登录检查拦截).
    // true : 放行  false :不放行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        System.out.println("拦截器执行了......");
        //从Session中获取登录信息
        String username = (String)request.getSession().getAttribute("username");
        System.out.println(username);

        if(username !=null) {
            //放行
            return true;
        }else {
            //跳转到登录页面去
            response.sendRedirect(request.getContextPath()+"/login.jsp");
            return false;
        }
    }

    //postHandle:控制器方法执行后,视图渲染之前执行(可以加入统一的响应信息).
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
    }

    //afterCompletion:视图渲染之后执行(处理Controller异常信息,记录操作日志,清理资源等
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    }
}

3.1.1. 拦截器的配置的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        ">

        <!-- 配置springmvc的注解驱动 -->
        <mvc:annotation-driven/>



        <!-- 配置拦截器 :可以有多个拦截器-->
        <mvc:interceptors>
            <!--配置检查登录拦截器  -->
            <mvc:interceptor>

                <!-- 配置拦截的规则
                    只会拦截 控制器请求,不会拦截jsp页面
                    /*
                        只能拦截一级 如 : /list.do /delete.do
                        如:/user/list.do , /user/delete.do 二级 不能拦截
                    /**
                        可以拦截多级 无论几级都可以 如  /a/b/c/d/list.do
                 -->
                <mvc:mapping path="/**"/>

                <!-- 排除拦截的地址,多个地址使用逗号隔开
                    /user/login.do


                 -->
                <mvc:exclude-mapping path="/user/login.do"/>

                <!-- 拦截器的类型 -->
                <bean class="cn.zj.ssm.interceptor.CheckLoginInterceptor"/>

            </mvc:interceptor>
        </mvc:interceptors>


</beans>

4. 使用poi组件导出excel文件

使用POI组件实现Excel数据的处理.

下载路径:Apache POI - the Java API for Microsoft Documents

4.1. 入门案例

4.1.1. 导入jar包

4.1.2. 案例代码

//使用POI创建excel文件到本地
    @Test
    public void testName() throws Exception {
        //1.创建数据,用于本地创建excel
        HSSFWorkbook book = new HSSFWorkbook();
        //2.创建一个sheet 工作区域
        HSSFSheet sheet = book.createSheet();
        //3.创建一行: 从0开始,代表第一行
        HSSFRow row = sheet.createRow(0);
        //4.创建一个个单元格
        HSSFCell cell1 = row.createCell(0);
        //5.设置单元格的数据
        cell1.setCellValue("张三");

        HSSFCell cell2 = row.createCell(1);
        cell2.setCellValue(20);

        //将数据保存到本地
        try {
            book.write(new File("d:/测试.xlsx"));
        } catch (Exception e) {
            e.printStackTrace();
            // TODO: handle exception
        }
    }

 4.2. 使用POI导出数据库的所有用户信息

// 导出用户信息
    @RequestMapping("/exprot")
    public void export(HttpServletResponse response) {


        //创建POI的数据对象
        HSSFWorkbook book = new HSSFWorkbook();
        //创建sheet
        HSSFSheet sheet = book.createSheet();
        //创建标题列
        HSSFRow titleRow = sheet.createRow(0);
        //创建表单单元格并设置值
        titleRow.createCell(0).setCellValue("编号");
        titleRow.createCell(1).setCellValue("姓名");
        titleRow.createCell(2).setCellValue("邮箱");
        titleRow.createCell(3).setCellValue("电话");

        List<User> users = service.list();
        //循环学生
        for (int i = 0; i < users.size(); i++) {
            //获取每个学生
            User user = users.get(i);
            //创建学生列
            HSSFRow row = sheet.createRow(i+1);
            //创建学生信息对应的单元格并设置数据
            row.createCell(0).setCellValue(user.getId());
            row.createCell(1).setCellValue(user.getName());
            row.createCell(2).setCellValue(user.getEmail());
            row.createCell(3).setCellValue(user.getPhone());
        }

        try {
            //设置响应头,响应的内容是为附件形式
            response.addHeader("Content-Disposition",
                    "attachment;filename=" + new String("学生信息.xlsx".getBytes(), "ISO-8859-1"));

            book.write(response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

5. SpringMVC 控制器 Controller的生命周期

Spring 容器创建的对象默认 都是单例 对象

SpringMVC对象 Controller的对象的创建有三种情况

Request : 在用户的一次请求中生效(用户每次请求都会创建Controller对象)多例

Session : Controller对象在一次会话中创建一个对象

如果控制器中有成员变量 设置或者赋值操作,必须使用 request 返回

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值