当前位置: 首页 > news >正文

Spring Boot中文件上传

Spring Boot中文件上传

前言

本篇主要参考Spring官方文档,整理了Spring Boot中文件上传如何实现,以及在代码中使用RestTemplate和HttpClient两种方式实现文件上传。

创建Spring Boot项目

首先创建一个Spring Boot Web项目,使用的Spring Boot版本为2.6.14,项目的pom文件如下:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.yzh</groupId><artifactId>uploadFile</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.14</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpmime</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency></dependencies>
</project>

主要功能

提供下面三个功能:

方法URL功能
POST/upload上传文件
GET/files获取文件列表
GET/files/{fileName}下载文件

具体实现

代码结构

在这里插入图片描述

主要功能实现

这边直接贴一下代码:

controller

/*** 文件上传** @author yuanzhihao* @since 2023/3/22*/
@RestController
@RequestMapping
public class FileUploadController {@Autowiredprivate FileUploadService fileUploadService;/*** 上传文件** @param files 文件* @return 响应消息*/@PostMapping("/upload")public ResponseEntity<String> upload(@RequestParam("files") MultipartFile[] files) {fileUploadService.upload(files);return ResponseEntity.ok("File Upload Success");}/*** 获取文件列表** @return 文件列表*/@GetMapping("/files")public ResponseEntity<List<FileInfo>> list() {return ResponseEntity.ok(fileUploadService.list());}/*** 获取指定文件** @param fileName 文件名称* @return 文件*/@GetMapping("/files/{fileName:.+}")public ResponseEntity<Resource> getFile(@PathVariable("fileName") String fileName) {return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION,"attachment; filename=\"" + fileName + "\"").body(fileUploadService.getFile(fileName));}
}

service

/*** 文件上传Service** @author yuanzhihao* @since 2023/3/27*/
public interface FileUploadService {void upload(MultipartFile[] files);List<FileInfo> list();Resource getFile(String fileName);
}
/*** 文件上传** @author yuanzhihao* @since 2023/3/27*/
@Service
@Slf4j
public class FileUploadServiceImpl implements FileUploadService {@Value("${upload.path:/data/upload/}")private String filePath;private static final List<FileInfo> FILE_STORAGE = new CopyOnWriteArrayList<>();@Overridepublic void upload(MultipartFile[] files) {SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");for (MultipartFile file : files) {String fileName = file.getOriginalFilename();boolean match = FILE_STORAGE.stream().anyMatch(fileInfo -> fileInfo.getFileName().equals(fileName));if (match) {throw new RuntimeException("File [ " + fileName + " ] already exist");}String currentTime = simpleDateFormat.format(new Date());try (InputStream in = file.getInputStream();OutputStream out = Files.newOutputStream(Paths.get(filePath + fileName))) {FileCopyUtils.copy(in, out);} catch (IOException e) {log.error("File [{}] upload failed", fileName, e);throw new RuntimeException(e);}FileInfo fileInfo = new FileInfo().setFileName(fileName).setUploadTime(currentTime);FILE_STORAGE.add(fileInfo);}}@Overridepublic List<FileInfo> list() {return FILE_STORAGE;}@Overridepublic Resource getFile(String fileName) {FILE_STORAGE.stream().filter(info -> info.getFileName().equals(fileName)).findFirst().orElseThrow(() -> new RuntimeException("File [ " + fileName + " ] not exist"));File file = new File(filePath + fileName);return new FileSystemResource(file);}
}

上传文件限制

可以在application.properties配置文件中限制上传单个文件的大小和所有文件的总大小,具体配置如下:

# 单个文件限制
spring.servlet.multipart.max-file-size=20MB
# 总大小限制
spring.servlet.multipart.max-request-size=100MB

测试验证

使用postman进行接口测试

文件上传

正常上传文件:
在这里插入图片描述
文件已存在:
在这里插入图片描述
上传超过20MB的文件:
在这里插入图片描述
上传总共超过100MB的文件:
在这里插入图片描述

查询文件列表

文件下载

正常文件下载:
在这里插入图片描述
下载不存在的文件:
在这里插入图片描述

代码中调用上传接口

主要整理了使用restTemplate和httpclient客户端如何在代码中调用文件上传接口。

使用restTemplate调用上传文件接口

@Test
public void uploadTestByRestTemplate() {HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.MULTIPART_FORM_DATA);MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();File file = new File("/Users/yuanzhihao/Downloads/mirrors-jenkins-master.zip");body.add("files", new FileSystemResource(file));body.add("files", new FileSystemResource(new File("/Users/yuanzhihao/Downloads/crictl-v1.22.0-linux-amd64.tar.gz")));body.add("files", new FileSystemResource(new File("/Users/yuanzhihao/Downloads/client(macosx).zip")));HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);String serverUrl = "http://localhost:8080/upload";RestTemplate restTemplate = new RestTemplate();ResponseEntity<String> response = restTemplate.postForEntity(serverUrl, requestEntity, String.class);System.out.println("Response code: " + response.getStatusCode() + " Response body: " + response.getBody());
}

使用httpclient调用上传文件接口

@Test
public void uploadTestByHttpClient() {File file = new File("/Users/yuanzhihao/Downloads/xzs-sql-v3.9.0.zip");FileBody fileBody = new FileBody(file, ContentType.DEFAULT_BINARY);MultipartEntityBuilder builder = MultipartEntityBuilder.create();builder.addPart("files", fileBody);HttpPost post = new HttpPost("http://localhost:8080/upload");org.apache.http.HttpEntity entity = builder.build();post.setEntity(entity);try (CloseableHttpClient client = HttpClientBuilder.create().build();CloseableHttpResponse response = client.execute(post)) {System.out.println("Response code: " + response.getStatusLine().getStatusCode());System.out.println("Response body: " + EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));} catch (IOException e) {throw new RuntimeException(e);}
}

结语

代码地址:https://github.com/yzh19961031/blogDemo/tree/master/uploadFile

参考:

https://spring.io/guides/gs/uploading-files/

https://www.baeldung.com/spring-rest-template-multipart-upload

https://www.bezkoder.com/spring-boot-file-upload/

http://www.lryc.cn/news/44468.html

相关文章:

  • Github上传大文件(>25MB)教程
  • 面试官:mysql索引会缓存内存吗?
  • bs4解析数据和csv文件
  • Linux中Buffer和Cache的区别
  • Docker 镜像使用
  • Java阶段一Day10
  • 触摸屏与PLC之间如何快速实现无线PPI通信?
  • 【华为OD机试 2023最新 】 羊、狼、农夫过河(C++ 100%)
  • Java中关于try、catch、finally中的细节分析
  • Zookeeper原理
  • 关于FPGA如何快速生成模块的例化模板(实用)
  • 在 Python 中将字符串转换为集合
  • 大数据Flink进阶(十三):Flink 任务提交模式
  • day11—编程题
  • CentOS下安装crontab及cron表达式解析
  • python 绘制训练曲线--基于Numpy.convolve曲线平均滤波
  • 状态管理插件vuex
  • arthas—阿里开源的Java诊断工具
  • Java学习记录
  • OpenGL API 之 glVertexAttribPointer
  • 蓝桥杯真题4
  • day02_基本语法
  • 多线程之单例模式
  • 2023年绿色建筑国际会议(ICoGB 2023) | Springer独立出版
  • Python中进程和线程到底有什么区别?
  • 2023美赛春季赛F题思路数据代码论文分享
  • 念一句咒语 AI 就帮我写一个应用,我人麻了...
  • 开放平台设计之接口签名认证
  • Vue自创插件发布到npm以及使用方法
  • 合成孔径雷达干涉测量InSAR数据处理、地形三维重建、形变信息提取、监测等实践技术