SpringMVC 学习(八)之文件上传与下载

目录

1 文件上传        

2 文件下载


1 文件上传        

 SpringMVC 对文件的上传做了很好的封装,提供了两种解析器。

  • CommonsMultipartResolver:兼容性较好,可以兼容 Servlet3.0 之前的版本,但是它依赖了 commons-fileupload 这个第三方工具,所以如果使用这个,一定要添加 commons-fileupload 依赖
  • StandardServletMultipartResolver:兼容性较差,它适用于 Servlet3.0 之后的版本,它不依赖第三方工具,使用它,可以直接做文件上传

本文使用 CommonsMultipartResolver 解析器,通过上传图片进行测试

导入依赖

导入 commons-fileupload.jar 包,Maven 会自动帮我们导入它的依赖包 commons-io.jar

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

在 SpringMVC 配置文件中配置 CommonsMultipartResolver  解析器

设置 <mvc:resources> 标签访问静态资源

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttps://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 扫描指定包下的注解 --><context:component-scan base-package="com.controller"/><!-- 配置访问静态资源 --><!-- img 必须是在 webapp 根目录下--><!-- <mvc:resources> 标签将路径 /img/** 映射到 /img/ 目录 --><!-- 这意味着当客户端访问 /img/** 路径时,SpringMVC会在 /img/ 目录下寻找对应的静态资源文件--><mvc:resources mapping="/img/**" location="/img/"/><!-- 配置注解驱动 --><mvc:annotation-driven/><!-- InternalResourceViewResolver 是 SpringMVC 中用于解析和渲染内部资源视图(通常是 JSP 页面)的视图解析器。它根据视图名称查找并加载对应的 JSP 文件,并将模型数据传递给 JSP 进行展示 --><!-- 配置 JSP 解析器 --><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!-- 配置前缀 --><property name="prefix" value="/WEB-INF/pages/"/><!-- 配置后缀 --><property name="suffix" value=".jsp"/><!-- 定义模板顺序 --></bean><!-- 配置文件上传数据专用的解析器 --><!-- 这个bean的id必须是multipartResolver,否则上传文件会报400的错误 --><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 设置文件编码格式 --><property name="defaultEncoding" value="utf-8"/><!-- 设置最大上传大小 --><property name="maxUploadSize" value="#{1024*1024}"/></bean>
</beans>

创建上传文件的控制器

      文件上传是使用 CommonsMultipartFile 还是 MultipartFile 呢?相信大家在学习上传文件时,肯定见过这两个类。额。。。没见过,正好可以了解下。

CommonsMultipartFile 和 MultipartFile 是 Java 中用于处理 HTTP 多部分表单数据 (Multipart Form Data) 的类。

  • CommonsMultipartFile 是 Apache Commons FileUpload 库提供的一个类,用于处理文件上传操作。它提供了更多的功能和方法,例如获取文件名、文件内容、文件类型等信息,以及设置文件的存储位置等
  • MultipartFile 是 Spring Framework 提供的一个类,用于处理文件上传和下载操作。它是基于 CommonsMultipartFile 实现的,并添加了一些 Spring 特定的功能和方法,例如通过注解进行文件解析和绑定等


        在使用时,如果你使用的是 Spring Framework,建议使用 MultipartFile 类,因为它与 Spring 的其他功能集成得更好。如果你需要更多的文件上传功能或与其他框架集成,可以考虑使用 CommonsMultipartFile 类。

        MultipartFile 封装了请求数据中的文件,此时这个文件存储在内存中或临时的磁盘文件中,需要将其转存到一个合适的位置,因为请求结束后临时存储将被清空。在 MultipartFile 接口中有如下方法:

方法名返回值描述
getContentType()String获取文件内容的类型
getOriginalFilename()String获取文件的原名称
getName()String获取 form 表单中文件组件的名字
getInputStream()InputStream将文件内容以输入流的形式返回
getSize()long获取文件的大小,单位为 byte
isEmpty()boolean文件是否为空
transferTo(File dest)void将数据保存到一个目标文件中
@Controller
public class TestController {@RequestMapping("/upload")public String testUp(MultipartFile photo, Model model, HttpSession session) throwsIOException {// 获取图片文件名// xxx.jpgString originalFilename = photo.getOriginalFilename();System.out.println(originalFilename);// 使用UUID给图片重命名,并且去掉UUID的四个"-"// UUID.randomUUID() 随机生成 36 位的字符串String fileName = UUID.randomUUID().toString().replaceAll("-", "");// f6522af8-3f9b-4d90-a51d-e153bdb06ec6//获取图片的后缀// lastIndexOf(".") 获得字符串中最后一个 "." 的下标// substring(startindex) 获得字符串中从 startindex 开始的子串,即 ".jpg"String extName = originalFilename.substring(originalFilename.lastIndexOf("."));// 拼接新的图片名称// f6522af83f9b4d90a51de153bdb06ec6 + .jpgString newFileName = fileName + extName;// 声明转存文件时,目标目录的虚拟路径(也就是浏览器访问服务器时,能够访问到这个目录的路径)// 该路径需要和 SpirngMVC 配置文件中 <mvc:resources> 标签设置的路径一致String virtualPath = "/img";// 通过 session 获得 servletContext 域对象ServletContext servletContext = session.getServletContext();// 获得 img 的绝对路径  D:\JavaWeb\SpringMVCTest\target\SpringMVCTest\imgString photoPath = servletContext.getRealPath(virtualPath);System.out.println("photoPath = " + photoPath);// 若 D:\JavaWeb\SpringMVCTest\target\SpringMVCTest\img 不存在,则创建File file = new File(photoPath);if (!file.exists()) {file.mkdir();}// 图片最终路径// D:\JavaWeb\SpringMVCTest\target\SpringMVCTest\img + f6522af83f9b4d90a51de153bdb06ec6.jpgString finalPath = photoPath + File.separator + newFileName;System.out.println("finalPath=" + finalPath);// 调用transferTo()方法实现文件转存,photo 是图片,photo.transferTo 相当于将图片复制到 该路径photo.transferTo(new File(finalPath));// 为了让下一个页面能够将图片展示出来,将图片访问路径存入模型,把访问图片的路径准备好// servletContext.getContextPath() 获得上下文路径,即 /SpringMVCTest// /SpringMVCTest + /img/ + f6522af83f9b4d90a51de153bdb06ec6.jpgString picPath = servletContext.getContextPath() + "/img/" + newFileName;System.out.println("picPath = " + picPath);model.addAttribute("picPath", picPath);return "success";}
}

index.jsp

上传文件的表单中有三点需要注意:

  • 要点1:请求方式必须是 POST
  • 要点2:enctype 属性必须是 multipart/form-data, 以二进制的方式传输数据
  • 要点3:文件上传框使用 input 标签,type 属性设置为 file,name 属性值和控制器的形参一致或通过 @RequestParam 注解重命名 name 属性值(请求参数的知识)

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

  • application/x-www=form-urlencoded:默认方式,只处理表单域中的 value 属性值,采用这种编码方式的表单会将表单域中的值处理成 URL 编码方式。
  • multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。
  • text/plain除了把空格转换为 “+” 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>文件上传</title></head><body><h1>上传演示案例</h1><form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">请选择上传的图片:<input type="file" name="photo"/><br/><input type="submit" value="上传文件"/></form></body>
</html>

success.jsp

        在控制器中,使用了 model 向 request 域对象传递了数据 picPath,可以在整个请求中使用该数据 ${picPath} 或 ${requestScope.picPath} (SpringMVC 域对象的知识)。要访问静态资源,可以在 SpringMVC 配置文件中设置 <mvc:resources> 标签。

<%@ page contentType="text/html;charset=UTF-8" %>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>Title</title></head><body><p>上传成功!!!</p><%-- 需要在 SpringMVC 配置文件中设置 <mvc:resources> 标签访问静态文件--%><img src="${picPath}" width="220" height="280" alt="找不到该图片"/></body>
</html>

执行过程

上传多张图片

修改 index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>文件上传</title></head><body><h1>上传演示案例</h1><form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">请选择上传的图片1:<input type="file" name="photos"/><br/>请选择上传的图片2:<input type="file" name="photos"/><br/>请选择上传的图片3:<input type="file" name="photos"/><br/><input type="submit" value="上传文件"/></form></body>
</html>

修改控制器

MultipartFile photo  -->  List<MultipartFile> photos,input 标签中 name 属性值改为 photos

@Controller
public class TestController {@RequestMapping("/upload")public String testUp(List<MultipartFile> photos, Model model, HttpSession session) throwsIOException {//用于存储发送至前台页面展示的路径List<String> filePathNames = new ArrayList<>();// 声明转存文件时,目标目录的虚拟路径(也就是浏览器访问服务器时,能够访问到这个目录的路径)String virtualPath = "/img";// 准备转存文件时,目标目录的路径。File对象要求这个路径是一个完整的物理路径。// 而这个物理路径又会因为在服务器上部署运行时所在的系统环境不同而不同,所以不能写死。// 需要调用servletContext对象的getRealPath()方法,将目录的虚拟路径转换为实际的物理路径ServletContext servletContext = session.getServletContext();// 获得 img 的绝对路径  D:\JavaWeb\SpringMVCTest\target\SpringMVCTest\imgString photoPath = servletContext.getRealPath(virtualPath);System.out.println("photoPath = " + photoPath);// 若 D:\JavaWeb\SpringMVCTest\target\SpringMVCTest\img 不存在,则创建File file = new File(photoPath);if (!file.exists()) {file.mkdir();}for (MultipartFile photo : photos) {// 获取图片文件名// xxx.jpgString originalFilename = photo.getOriginalFilename();System.out.println(originalFilename);// 使用UUID给图片重命名,并且去掉UUID的四个"-"String fileName = UUID.randomUUID().toString().replaceAll("-", "");// f6522af8-3f9b-4d90-a51d-e153bdb06ec6//获取图片的后缀// lastIndexOf(".") 获得字符串中最后一个 "." 的下标// substring(startindex) 获得字符串中从 startindex 开始的子串,即 ".jpg"String extName = originalFilename.substring(originalFilename.lastIndexOf("."));// 拼接新的图片名称// f6522af83f9b4d90a51de153bdb06ec6 + .jpgString newFileName = fileName + extName;// 图片最终路径// D:\JavaWeb\SpringMVCTest\target\SpringMVCTest\img + f6522af83f9b4d90a51de153bdb06ec6.jpgString finalPath = photoPath + File.separator + newFileName;System.out.println("finalPath=" + finalPath);// 调用transferTo()方法实现文件转存,photo 是图片,photo.transferTo 相当于将图片复制到 该路径photo.transferTo(new File(finalPath));// 为了让下一个页面能够将图片展示出来,将图片访问路径存入模型,把访问图片的路径准备好// servletContext.getContextPath() 获得上下文路径,即 /SpringMVCTest// /SpringMVCTest + /img/ + f6522af83f9b4d90a51de153bdb06ec6.jpgString picPath = servletContext.getContextPath() + "/img/" + newFileName;System.out.println("picPath = " + picPath);filePathNames.add(picPath);}for(int i = 0;i < filePathNames.size(); i++) {model.addAttribute("picPath" + (i + 1), filePathNames.get(i));}return "success";}
}

修改 success.jsp


<%@ page contentType="text/html;charset=UTF-8" %>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>Title</title></head><body><p>上传成功!!!</p><%-- 需要在 SpringMVC 配置文件中设置 <mvc:resources> 标签访问静态文件--%><div><img src="${picPath1}" width="220" height="280" alt="找不到该图片"/><img src="${picPath2}" width="220" height="280" alt="找不到该图片"/><img src="${picPath3}" width="220" height="280" alt="找不到该图片"/></div></body>
</html>

运行结果

2 文件下载

文件下载控制器

        传统 Servlet 文件下载方式,需要在 HttpServletResponse response 中设置各种信息,而使用 SpringMVC 的 ResponseEntity 只需要将文件二进制主体、头信息以及状态码设置好即可进行文件下载,在易用性和简洁上更胜一筹。

@RequestMapping(value = "/download")
public ResponseEntity<byte[]> testResponseEntity(String picPath, HttpSession session) throwsIOException {// 获取ServletContext对象ServletContext servletContext = session.getServletContext();// 获取文件所在目录及文件名// picPath=/SpringMVCTest/img/05bba37fc8bc4fdfb095f41a6d2c904a.jpgString direcfile = "/img" + picPath.substring(picPath.lastIndexOf("/"));// 获取文件绝对路径String realPath = servletContext.getRealPath(direcfile);System.out.println("realPath=" + realPath);File file = new File(realPath);// 创建输入流InputStream is = new FileInputStream(file);// 创建字节数组byte[] bytes = new byte[is.available()];// 将流读到字节数组中is.read(bytes);// 创建HttpHeaders对象设置响应头信息MultiValueMap<String, String> headers = new HttpHeaders();// 设置下载文件的名字headers.add("Content-Disposition", "attachment; filename=" + file.getName());// 设置响应状态码HttpStatus statusCode = HttpStatus.OK;// 创建ResponseEntity对象ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);//关闭输入流is.close();return responseEntity;
}

修改 success.jsp


<%@ page contentType="text/html;charset=UTF-8" %>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>Title</title></head><body><p>上传成功!!!</p><%-- 需要在 SpringMVC 配置文件中设置 可以访问静态文件--%><div><img src="${picPath}" width="220" height="280" alt="找不到该图片"/></div><a href="${pageContext.request.contextPath}/download?picPath=${picPath}">点击下载图片</a></body>
</html>

演示过程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2814577.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

kubectl 命令行管理K8S(上)

目录 陈述式资源管理方式 介绍 命令 项目的生命周期 创建 kubectl create命令 发布 kubectl expose命令 更新 kubectl set 回滚 kubectl rollout 删除 kubectl delete 应用发布策略 金丝雀发布 陈述式资源管理方式 介绍 1.kubernetes 集群管理集群资源…

python 基础知识点(蓝桥杯python科目个人复习计划53)

今日复习内容&#xff1a;做题 例题1&#xff1a;最大的卡牌价值 问题描述&#xff1a; 给定n副卡牌&#xff0c;每张卡牌具有正反面&#xff0c;正面朝上数字为ai&#xff0c;背面朝上数字为bi。一副卡牌的价值为正面朝上数字之和&#xff0c;一开始所有卡牌都是正面朝上的…

【已解决】用ArcGIS处理过的数据在QGIS中打开发生偏移怎么办?| 数据在ArcGIS中打开位置正常,在QGIS中偏移

1. 问题描述 栅格或者矢量数据用ArcGIS打开时位置正确&#xff08;可以和其他数据对应上&#xff09;。但是用QGIS打开后发现位置不对 2. 问题的原因 因为该数据用了ArcGIS自定义的坐标系&#xff0c;QGIS不支持&#xff0c;识别有误。因此在数据QGIS中的坐标系参数有误&a…

HTTP 的 multipart 类型

上一篇文章讲到 http 的 MIME 类型 http MIME 类型 里有一个 multipart 多部分对象集合类型&#xff0c;这个类型 http 指南里有讲到&#xff1a;MIME 中的 multipart&#xff08;多部分&#xff09;电子邮件报文中包含多个报文&#xff0c;它们合在一起作为单一的复杂报文发送…

【生态适配】亚信安慧AntDB数据库与FT-2000+/64处理器完成兼容互认

日前&#xff0c;亚信安慧AntDB数据库完成了与FT-2000/64处理器的兼容互认。经湖南亚信安慧科技有限公司&#xff08;简称“亚信安慧”&#xff09;与飞腾信息技术有限公司&#xff08;简称“飞腾公司”&#xff09;的严格测试&#xff0c;亚信安慧AntDB数据库V6.2在FT-2000/64…

《大模型时代-ChatGPT开启通用人工智能浪潮》精华摘抄

原书很长&#xff0c;有19.3w字&#xff0c;本文尝试浓缩一下其中的精华。 知识点 GPT相关 谷歌发布LaMDA、BERT和PaLM-E&#xff0c;PaLM 2 Facebook的母公司Meta推出LLaMA&#xff0c;并在博客上免费公开LLM&#xff1a;OPT-175B。 在GPT中&#xff0c;P代表经过预训练(…

一看就会:使用nvm实现多个版本的node自由切换

一、介绍 使用nvm可以方便的在同一台设备上进行多个node版本之间切换&#xff0c;解决不同的项目所使用的node版本不一样的问题 二、安装nvm 如果已安装node环境先卸载后再安装nvm&#xff0c;防止出现不确定错误 1、卸载node环境&#xff0c;并清除node环境变量配置 通过…

【README 小技巧】 展示gitee中开源项目start

【README 小技巧】 展示gitee中开源项目start <a target"_blank" hrefhttps://gitee.com/wujiawei1207537021/wu-framework-parent><img srchttps://gitee.com/wujiawei1207537021/wu-framework-parent/badge/star.svg altGitee star/></a>

我在使用 Copilot 时遇到了许可证验证错误。

如果使用的是 Copilot&#xff0c;并收到以下错误消息&#xff0c;请按以下步骤进行操作&#xff1a; We encountered a problem validating your Copilot license. For more information, see https://aka.ms/copilotlicensecheck 请确保使用的是正确的帐户 请确保已使用具…

Flink动态分区裁剪

1 原理 1.1 静态分区裁剪与动态分区裁剪 静态分区裁剪的原理跟谓词下推是一致的&#xff0c;只是适用的是分区表&#xff0c;通过将where条件中的分区条件下推到数据源达到减少分区扫描的目的   动态分区裁剪应用于Join场景&#xff0c;这种场景下&#xff0c;分区条件在joi…

kafka平滑升级过程指导

一、前言 Apache Kafka作为常用的开源分布式流媒体平台&#xff0c;可以实时发布、订阅、存储和处理数据流,多用于作为消息队列获取实时数据&#xff0c;构建对数据流的变化进行实时反应的应用程序&#xff0c;已被数千家公司用于高性能数据管道、流分析、数据集成和任务关键型…

算法day01_ 27. 移除元素、977.有序数组的平方

推荐阅读 从零开始学数组&#xff1a;深入浅出&#xff0c;带你掌握核心要点 初探二分法 再探二分法 系统的纪录一下刷算法的过程&#xff0c;之前一直断断续续的刷题&#xff0c;半途而废&#xff0c;现在重新开始。话不多说&#xff0c;开冲&#xff01; 27.移除元素 题目 给…

js 面试 什么是WebSockets?HTTP和HTTPS有什么不同?web worker是什么?

概念&#xff1a; webSocket 是一种在客户端和服务端之间建立持久连接的协议&#xff0c;它提供全双工通信通道&#xff0c;是服务器可以主动向客户端推送数据&#xff0c;同时也可以接受客户端发送的数据。 1 webSocket与https区别&#xff1f; 在网络通信中&#xff0c;We…

Acceptor监听套接字管理类实现(模块七)

目录 类功能 类定义 类实现 编译测试 类功能 类定义 // 监听套接字管理类 class Acceptor { private:Socket _socket; // 用于创建监听套接字EventLoop *_loop; // 用于对监听套接字进行事件监控Channel _channel; // 用于对监控套接字进行事件管理using AcceptCallback…

11 PLL IP核

PLL IP 核简介 锁相环&#xff08;PLL&#xff09;作为一种反馈控制电路&#xff0c;其特点是利用外部输入的参考信号来控制环路内部震荡信号的频率和相位。因为锁相环可以实现输出信号频率对输入信号频率的自动跟踪&#xff0c;所以锁相环通常用于闭环跟踪电路。锁相环在工作…

36.云原生之SpringCloud+k8s实践

云原生专栏大纲 文章目录 SpringCloudk8s介绍spring-cloud-kubernetes服务发现配置管理负载均衡选主 spring-cloud-bookinfo案例构建项目环境配置namespace部署与验证productpagegatewaybookinfo-admindetailsratingsreviewsreviews-v1reviews-v2 总结 SpringCloudk8s介绍 ht…

React UI框架Antd 以及 如何按需引入css样式配置(以及过程中各种错误处理方案)

一、react UI框架Antd使用 1.下载模块 npm install antd -S 2.引入antd的样式 import ../node_modules/antd/dist/reset.css; 3.局部使用antd组件 import {Button, Calendar} from antd; import {PieChartTwoTone} from ant-design/icons; {/* 组件汉化配置 */} import l…

SORA 到底是什么?如何用bitget wallet购买?

什么是SORA&#xff1f; SORA 是一种模因币&#xff0c;灵感来自 OpenAI 最新的人工智能模型 Sora&#xff0c;它巧妙地根据文本输入生成视频。 SORA 诞生于加密社区内人工智能项目的热潮中&#xff0c;利用 OpenAI 的公告推出了一种独特且时尚的数字资产。正如 memecoin 网站…

【管理咨询宝藏资料28】某信息技术有限公司战略规划报告

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏资料28】某信息技术有限公司战略规划报告 【关键词】战略规划、对标研究、管理咨询 【文件核心观点】 - 使企业实现商业流程整合&#xff0c;构…

宏集小型PLC应用于浮动封盖机

导言 仅通过1个控制面板和1个紧凑型PLC控制自动化设备中来自不同制造商的13种不同电机&#xff0c;听起来难以置信&#xff01;但这是宏集科技已经落地的合作项目&#xff01; 案例概况 客户&#xff1a;TREPAK 合作伙伴&#xff1a;SDT 应用&#xff1a;封盖机 应用产品&…