文件操作包括文件上传
和文件下载
。
用户将自己计算机中文件上传到项目所在服务器|文件服务器|OSS的过程 称之为文件上传;文件下载则相反。下面我们先来看下文件上传
由于本次案例会涉及到页面(jsp)操作,所以不要忘记添加配置jsp相关的东西
新建Module - springboot-07-file
,按照下图所示填写信息:
点击下一步选择依赖Spring Web
,点击Finish
。如下图所示:
我们在springboot-06-AOP
中的代码上进行改造。首先我们规整一下项目,然后将springboot-06-AOP
中的代码拷贝过来,去除AOP相关的代码。如下图所示:
pom.xml
文件中新增了jsp有关的依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
<relativePath/>
</parent>
<groupId>com.christy</groupId>
<artifactId>springboot-07-file</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-07-file</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring-boot-starter-test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<!-- mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<!-- mybatis-spring-boot-starter
由于springboot整合mybatis版本中默认依赖mybatis 因此不需要额外引入mybati版本,否则会出现冲突
-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!-- 每次新建的项目如果需要开启热部署都需要引入该依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- c标签库 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- 让内嵌tomcat具有解析jsp功能 -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<!-- 文件上传相关 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
<exclusions>
<exclusion>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 一定要注意mvn的插件一定是1.4.2.RELEASE,否则jsp访问不到 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.4.2.RELEASE</version>
</plugin>
</plugins>
<resources>
<!-- 打包时将jsp文件拷贝到META-INF目录下-->
<resource>
<!-- 指定resources插件处理哪个目录下的资源文件 -->
<directory>src/main/webapp</directory>
<!-- 注意必须要放在此目录下才能被访问到 -->
<targetPath>META-INF/resources</targetPath>
<includes>
<include>**/**</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/**</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
server:
port: 8807
# 修改jsp无须重启应用
servlet:
jsp:
init-parameters:
development: true
# datasource
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/christy?characterEncoding=UTF-8
username: root
password: 123456
# 配置视图解析器
mvc:
view:
prefix: / #这个代表jsp的根路径 需要在java包下新建webapp目录
suffix: .jsp
# 配置文件上传大小
servlet:
multipart:
max-request-size: 10MB # 设置请求的数据最大为10MB
max-file-size: 10MB # 设置能够处理的单个文件最大值为10MB
# mybatis
mybatis:
mapper-locations: classpath:com/christy/mapper/*.xml
type-aliases-package: com.christy.entity
# logback
# logging:
# level:
# root: info # 指定全局根日志级别为INFO(默认)
# com.christy.mapper: debug # 指定包级别日志为debug,在控制台不打印DEBUG日志时能看到sql语句
# 多环境下我们需要指定当前使用的日志文件
logging:
config: classpath:logs/logback-spring-dev.xml
# 文件上传路径
file:
# window下文件上传路径
windows:
path: G:/files/
# linux下文件上传路径
linux:
path: /usr/files/
# 虚拟路径
virtual:
path: /files/
有关配置相关说明
1.设置文件上传大小
# 配置文件上传大小
servlet:
multipart:
max-request-size: 10MB # 设置请求的数据最大为10MB
max-file-size: 10MB # 设置能够处理的单个文件最大值为10MB
SpringBoot默认上传大小是1048576 bytes,也就是1MB(也有说是10MB的,但是我的是1MB),这里改为10MB,否则会报如下错误:
2.设置文件上传路径及虚拟路径
# 文件上传路径
file:
# window下文件上传路径
windows:
path: G:/files/
# linux下文件上传路径
linux:
path: /usr/files/
# 虚拟路径
virtual:
path: /files/
我们选择Edit Configuration
,在Working directory
中选择MODULE_DIR
,然后点击Apply
->OK
。如下图所示:
<%@ page pageEncoding="UTF-8" language="java" contentType="text/html; UTF-8" %>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>springboot文件上传</title>
</head>
<body>
<h1>文件上传</h1>
<%--
method:post 含有文件上传的页面提交方式必须是POST
enctype:该属性规定在发送到服务器之前应该如何对表单数据进行编码
默认地,表单数据会编码为 "application/x-www-form-urlencoded"。就是说,在发送到服务器之前,
所有字符都会进行编码(空格转换为 "+" 加号,特殊符号转换为 ASCII HEX 值)。但是该种方式不能编码文件
在有文件的情况下,该值要修改为:multipart/form-data
--%>
<form action="${pageContext.request.contextPath}/file/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="上传">
</form>
</body>
</html>
import com.christy.utils.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @Author Christy
* @Date 2021/9/14 16:28
**/
@Controller
@RequestMapping("/file")
public class FileController {
private FileUtils fileUtils;
@Autowired
public FileController(FileUtils fileUtils) {
this.fileUtils = fileUtils;
}
/**
* MultipartFile file: 文件接收对象 file变量名要与form表单中input type="file"标签中的name属性一致
*
* @author Christy
* @date 2021/9/15 13:57
* @param request
* @return java.lang.String
*/
@RequestMapping("/upload")
@ResponseBody
public String upload(HttpServletRequest request) {
try {
fileUtils.fileUpload(request);
} catch (IOException e) {
e.printStackTrace();
return "文件上传失败";
}
return "文件上传成功";
}
}
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @Author Christy
* @Date 2021/9/15 16:35
**/
@Component
public class FileConstants {
/**
* windows文件上传储存的地址
*/
public static String fileWindowsPath;
/**
* linux文件上传储存的地址
*/
public static String fileLinuxPath;
/**
* 文件上传虚拟路径
*/
public static String fileVirtualPath;
@Value("${file.windows.path}")
public void setFileWindowsPath(String w) {
fileWindowsPath = w;
}
@Value("${file.linux.path}")
public void setFileLinuxPath(String l) {
fileLinuxPath = l;
}
@Value("${file.virtual.path}")
public void setFileVirtualPath(String v) {
fileVirtualPath = v;
}
}
import com.christy.constants.FileConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.UUID;
/**
* @Author Christy
* @Date 2021/9/15 14:29
**/
@Component
@Slf4j
public class FileUtils {
public String getRealPath(){
String filePath = "";
String os = System.getProperty("os.name");
if(os.toLowerCase().startsWith("win")){
filePath = FileConstants.fileWindowsPath;
} else {
filePath = FileConstants.fileLinuxPath;
}
File file = new File(filePath);
if(!file.exists() || !file.isDirectory()){
file.mkdirs();
}
return filePath;
}
public void fileUpload(HttpServletRequest request) throws IOException {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
if (multipartResolver.isMultipart(request)) {
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
Iterator<String> iterator = multiRequest.getFileNames();
while (iterator.hasNext()) {
// 上传的文件
MultipartFile item = multiRequest.getFile(iterator.next());
if (item != null) {
log.info("文件名:" + item.getOriginalFilename());
log.info("文件类型:" + item.getContentType());
log.info("文件大小:" + item.getSize());
// 文件的原始名称
String originalFilename = item.getOriginalFilename();
String ext = originalFilename.substring(originalFilename.lastIndexOf("."));
// 如果名称不为“”,说明该文件存在,否则说明该文件不存在
if (!"".equals(originalFilename.trim())) {
String newFileName = UUID.randomUUID() + ext;
String filePath = getRealPath();
//不是图片,直接保存
item.transferTo(new File(filePath, newFileName));
}
}
}
}
}
}
import com.christy.constants.FileConstants;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Author Christy
* @Date 2021/9/15 16:24
**/
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
/**
* 文件上传到服务器后并不能在项目中直接访问,需要将磁盘路径映射成虚拟路径使用http://domain/的方式才可以
*/
String os = System.getProperty("os.name");
if(os.toLowerCase().startsWith("win")){
// Windows虚拟路径映射本地磁盘
registry.addResourceHandler(FileConstants.fileVirtualPath + "**").addResourceLocations("file:" + FileConstants.fileWindowsPath);
} else {
// Linux虚拟路径映射本地磁盘
registry.addResourceHandler(FileConstants.fileVirtualPath + "**").addResourceLocations("file:" + FileConstants.fileLinuxPath);
}
}
}
我们启动项目,浏览器打开upload.jsp
页面,我们选择一张图片。如下所示:
点击上传按钮,注意观察控制台和页面。成功的情况如下所示:
我们在浏览器中访问http://localhost:8807/files/e8fdb612-1fe8-4e4c-a3df-04297eef0267.jpg
,图片能够正常加载。如下图所示:
我们启动虚拟机Christy(BaseOS)
,IP地址为192.168.8.100
。进入到/usr/apps/
目录下,上传jar包至该目录。如下图所示:
执行java -jar springboot-07-file-0.0.1-SNAPSHOT.jar
命令,启动该项目。如下图所示:
我们在浏览器中访问http://192.168.8.100:8807/upload.jsp
,还是选择上面的图片。如下图所示:
点击上传,页面返回文件上传成功
,控制台也能够打印输出文件信息。如下图所示:
我们回到目录/usr/files
,可以找到刚才上传的图片。如下图所示:
我们 浏览器访问http://192.168.8.100:8807/files/29b3b42c-f72f-462a-b6f9-d19afcfeab1c.jpg
,图片也可以正常加载。如下图所示:
相比较于文件上传,文件下载就简单多了。首先我们要提供文件的下载地址,就拿上面我们上传的照片来说,他的访问地址就是我们的下载地址
在Windows中的下载地址:
http://localhost:8807/files/e8fdb612-1fe8-4e4c-a3df-04297eef0267.jpg
在Linux中的下载地址:
http://192.168.8.100:8807/files/29b3b42c-f72f-462a-b6f9-d19afcfeab1c.jpg
<%@ page pageEncoding="UTF-8" language="java" contentType="text/html; UTF-8" %>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>springboot文件下载</title>
</head>
<body>
<h1>文件下载</h1>
<%--
a标签里面的filePath就是我们最终保存到数据库中的文件路径,这里不要搞错了
--%>
<a
href="${pageContext.request.contextPath}/file/download?fileName=e8fdb612-1fe8-4e4c-a3df-04297eef0267.jpg&filePath=/files/e8fdb612-1fe8-4e4c-a3df-04297eef0267.jpg">
睡美人-windows
</a>
<br/>
<a
href="${pageContext.request.contextPath}/file/download?fileName=29b3b42c-f72f-462a-b6f9-d19afcfeab1c.jpg&filePath=/files/29b3b42c-f72f-462a-b6f9-d19afcfeab1c.jpg">
睡美人-linux</a>
</body>
</html>
import com.christy.utils.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author Christy
* @Date 2021/9/14 16:28
**/
@RestController
@RequestMapping("/file")
public class FileController {
private FileUtils fileUtils;
@Autowired
public FileController(FileUtils fileUtils) {
this.fileUtils = fileUtils;
}
/**
* MultipartFile file: 文件接收对象 file变量名要与form表单中input type="file"标签中的name属性一致
*
* @author Christy
* @date 2021/9/15 13:57
* @param request
* @return java.lang.String
*/
@RequestMapping("/upload")
public String upload(HttpServletRequest request) {
try {
fileUtils.fileUpload(request);
} catch (IOException e) {
e.printStackTrace();
return "文件上传失败";
}
return "文件上传成功";
}
@RequestMapping("/download")
public String download(HttpServletResponse response, String fileName, String filePath){
try {
return fileUtils.fileDownload(response, fileName, filePath);
} catch (IOException e) {
e.printStackTrace();
return "文件下载失败!";
}
}
}
import com.christy.constants.FileConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.UUID;
/**
* @Author Christy
* @Date 2021/9/15 14:29
**/
@Component
@Slf4j
public class FileUtils {
/**
* 获取文件上传的真实路径
* @author Christy
* @date 2021/9/17 10:02
* @param
* @return java.lang.String
*/
public String getUploadRealPath(){
String filePath = "";
String os = System.getProperty("os.name");
if(os.toLowerCase().startsWith("win")){
filePath = FileConstants.fileWindowsPath;
} else {
filePath = FileConstants.fileLinuxPath;
}
File file = new File(filePath);
if(!file.exists() || !file.isDirectory()){
file.mkdirs();
}
return filePath;
}
/**
* 获取文件下载的真实路径
* @author Christy
* @date 2021/9/17 10:02
* @param
* @return java.lang.String
*/
public String getDownloadRealPath(String filePath){
String realPath = "";
if(filePath.indexOf(FileConstants.fileVirtualPath) == 0){
String os = System.getProperty("os.name");
// 将文件的虚拟路径替换成物理路径
if(os.toLowerCase().startsWith("win")){
StringBuilder stringbuilder = new StringBuilder(filePath);
stringbuilder.replace(0, FileConstants.fileVirtualPath.length(), FileConstants.fileWindowsPath);
realPath = stringbuilder.toString();
} else {
StringBuilder stringbuilder = new StringBuilder(filePath);
stringbuilder.replace(0, FileConstants.fileVirtualPath.length(), FileConstants.fileLinuxPath);
realPath = stringbuilder.toString();
}
}
return realPath;
}
public void fileUpload(HttpServletRequest request) throws IOException {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
if (multipartResolver.isMultipart(request)) {
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
Iterator<String> iterator = multiRequest.getFileNames();
while (iterator.hasNext()) {
// 上传的文件
MultipartFile item = multiRequest.getFile(iterator.next());
if (item != null) {
log.info("文件名:" + item.getOriginalFilename());
log.info("文件类型:" + item.getContentType());
log.info("文件大小:" + item.getSize());
// 文件的原始名称
String originalFilename = item.getOriginalFilename();
String ext = originalFilename.substring(originalFilename.lastIndexOf("."));
// 如果名称不为“”,说明该文件存在,否则说明该文件不存在
if (!"".equals(originalFilename.trim())) {
String newFileName = UUID.randomUUID() + ext;
String filePath = getUploadRealPath();
//不是图片,直接保存
item.transferTo(new File(filePath, newFileName));
}
}
}
}
}
public String fileDownload(HttpServletResponse response, String fileName, String filePath) throws IOException {
log.info("当前下载文件名为: {}",fileName);
log.info("当前下载文件目录: {}",filePath);
// 获取文件的真实存储路径
String realPath = getDownloadRealPath(filePath);
File file = new File(realPath);
if(file.exists()){
// 将文件读取为文件输入流
FileInputStream is = new FileInputStream(file);
// 获取响应流之前 一定要设置以附件形式下载 attachment:附件
response.setHeader("content-disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
// 获取响应输出流
ServletOutputStream os = response.getOutputStream();
// 输入流复制给输出流
/*int len=0;
byte[] b = new byte[1024];
while(true){
len = is.read(b);
if(len==-1) break;
os.write(b,0,len);
}*/
FileCopyUtils.copy(is,os);
log.info("文件下载成功!");
} else {
return "文件不存在";
}
return "文件下载成功!";
}
}
为了区别于下载时获取屋里路径的方法getDownloadRealPath()
,这里将上传时获取真实路径的方法改成了getUploadRealPath()
。
我们启动项目,在浏览器访问http://localhost:8807/download.jsp
,然后在界面中点击睡美人-windows
下载图片(这里不要点击linux下的),注意观察界面与控制台。如下图所示:
我们重新打包当前项目,传至linux服务器上,执行命令java -jar springboot-07-file-0.0.1-SNAPSHOT.jar
重新启动该项目。如下图所示:
然后浏览器访问http://192.168.8.100:8807/download.jsp
,点击睡美人-linux
,注意观察页面和控制台。如下图所示:
《新程序员》:云原生和全面数字化实践
50位技术专家共同创作,文字、视频、音频交互阅读
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://hardy.blog.csdn.net/article/details/120344431
内容来源于网络,如有侵权,请联系作者删除!