虽然在实际的项目中,借助RestTemplate来实现文件上传的机会不多(比如我已经开webclient的新坑了,才发现忘了这货…),但是这个知识点也还是有必要了解一下的,本文将简单介绍一下单个文件上传,多个文件上传的使用姿势
本项目基于SpringBoot 2.2.1.RELEASE
+ maven 3.5.3
+ idea
进行开发
核心pom依赖如下
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
提供两个简单的上传文件的接口,下面给出两种不一样的写法,效果差不多
/** * 文件上传 * * @param file * @return */ @PostMapping(path = "upload") public String upload(@RequestPart(name = "data") MultipartFile file, String name) throws IOException { String ans = new String(file.getBytes(), "utf-8") + "|" + name; return ans; } @PostMapping(path = "upload2") public String upload(MultipartHttpServletRequest request) throws IOException { List<MultipartFile> files = request.getFiles("data"); List<String> ans = new ArrayList<>(); for (MultipartFile file : files) { ans.add(new String(file.getBytes(), "utf-8")); } return JSON.toJSONString(ans); }
在Resource资源目录下,新建两个用于测试上传的文本文件,内容分别如下
文件1 test.txt
:
hello 一灰灰 天气不错哦:stuck_out_tongue_closed_eyes:
文件2 test2.txt
:
hello 二灰灰 天气还可以哦:stuck_out_tongue_closed_eyes:
简单设置一下日志格式,在 application.yml
文件中
logging: pattern: console: (%msg%n%n){blue}
文件上传,依然是走的POST请求,所以基本操作知识和前面的POST差不多,唯一的区别在于传参
文件上传两个核心步骤
最基础的单文件上传姿势实例如下,主要是借助 FileSystemResource
来获取文件并上传
RestTemplate restTemplate = new RestTemplate(); //设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); //设置请求体,注意是LinkedMultiValueMap FileSystemResource fileSystemResource = new FileSystemResource(this.getClass().getClassLoader().getResource("test.txt").getFile()); MultiValueMap<String, Object> form = new LinkedMultiValueMap<>(); // post的文件 form.add("data", fileSystemResource); // post的表单参数 form.add("name", "哒哒哒"); //用HttpEntity封装整个请求报文 HttpEntity<MultiValueMap<String, Object>> files = new HttpEntity<>(form, headers); String ans = restTemplate.postForObject("http://127.0.0.1:8080/upload", files, String.class); log.info("upload fileResource return: {}", ans);
当需要后端发起上传文件时,一般来讲是更多的情况下是上传二进制(or流),不太会是文件上传,所以更常见的是 InputStreamResource
的使用姿势
InputStream stream = this.getClass().getClassLoader().getResourceAsStream("test.txt"); InputStreamResource inputStreamResource = new InputStreamResource(stream) { @Override public long contentLength() throws IOException { // 这个方法需要重写,否则无法正确上传文件;原因在于父类是通过读取流数据来计算大小 return stream.available(); } @Override public String getFilename() { return "test.txt"; } }; form.clear(); form.add("data", inputStreamResource); files = new HttpEntity<>(form, headers); ans = restTemplate.postForObject("http://127.0.0.1:8080/upload", files, String.class); log.info("upload streamResource return: {}", ans);
InputStreamResource
重写了 contentLength()
, getFilename()
方法,去掉这个就没法正常的上传文件了 当然除了 InputStreamResource
之外, ByteArrayResource
也是一个比较好的选择
ByteArrayResource byteArrayResource = new ByteArrayResource("hello 一灰灰:stuck_out_tongue_closed_eyes:".getBytes()) { @Override public String getFilename() { return "test.txt"; } }; form.clear(); form.add("data", byteArrayResource); files = new HttpEntity<>(form, headers); ans = restTemplate.postForObject("http://127.0.0.1:8080/upload", files, String.class); log.info("upload bytesResource return: {}", ans);
ByteArrayResource
重写了 getFilename()
方法,感兴趣的小伙伴可以测试一下没有它的情况 上面介绍的是单文件上传,当然我们也会出现一次上传多个文件的情况,使用姿势和前面基本上一样,无非是传参的时候多传两个而已
// 多个文件上传 FileSystemResource f1 = new FileSystemResource(this.getClass().getClassLoader().getResource("test.txt").getFile()); FileSystemResource f2 = new FileSystemResource(this.getClass().getClassLoader().getResource("test2.txt").getFile()); form.clear(); form.add("data", f1); form.add("data", f2); form.add("name", "多传"); files = new HttpEntity<>(form, headers); ans = restTemplate.postForObject("http://127.0.0.1:8080/upload2", files, String.class); log.info("multi upload return: {}", ans);
尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激
下面一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
打赏 如果觉得我的文章对您有帮助,请随意打赏。