赞
踩
本篇主要参考Spring官方文档,整理了Spring Boot中文件上传如何实现,以及在代码中使用RestTemplate和HttpClient两种方式实现文件上传。
首先创建一个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 { @Autowired private 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<>(); @Override public 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); } } @Override public List<FileInfo> list() { return FILE_STORAGE; } @Override public 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客户端如何在代码中调用文件上传接口。
@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()); }
@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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。