厦门网站建设 智多星搜索引擎营销的原理
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/