一灰灰blog 一灰灰blog
首页
  • InfluxDB
  • MongoDB
  • MySql
  • 基础系列
  • DB系列
  • 搜索系列
  • MQ系列
  • WEB系列
  • 中间件
  • 运维
  • SpringSecurity
  • SpringCloud
  • QuickAlarm
  • QuickCrawer
  • QuickFix
  • QuickMedia
  • QuickSpi
  • QuickTask
  • 高可用
  • 分类
  • 标签
  • 归档
  • 收藏
  • 关于
GitHub (opens new window)

一灰灰blog

资深搬运工
首页
  • InfluxDB
  • MongoDB
  • MySql
  • 基础系列
  • DB系列
  • 搜索系列
  • MQ系列
  • WEB系列
  • 中间件
  • 运维
  • SpringSecurity
  • SpringCloud
  • QuickAlarm
  • QuickCrawer
  • QuickFix
  • QuickMedia
  • QuickSpi
  • QuickTask
  • 高可用
  • 分类
  • 标签
  • 归档
  • 收藏
  • 关于
GitHub (opens new window)
  • 基础系列

  • DB系列

  • 搜索系列

  • MQ系列

  • WEB系列

    • Request

    • Response

    • RestTemplate

      • 【WEB系列】RestTemplate基础用法小结
      • 【WEB系列】RestTemplate之自定义请求头
      • 【WEB系列】RestTemplate之中文乱码问题fix
      • 【WEB系列】RestTemplate之超时设置
      • 【WEB系列】RestTemplate之代理访问
      • 【WEB系列】RestTemplate之Basic Auth授权
      • 【WEB系列】RestTemplate之非200状态码信息捕获
      • 【WEB系列】AsyncRestTemplate之异步非阻塞网络请求介绍篇
      • 【WEB系列】RestTemplate之文件上传
        • I. 项目搭建
          • 1. pom依赖
          • 2. Rest服务
          • 3. 上传文件
        • II. 项目实现
          • 1. 文件上传
          • 2. 多文件上传
          • 3. 输出结果
        • II. 其他
          • 0. 项目&系列博文
          • 1. 一灰灰Blog
      • 【WEB系列】RestTemplate之连接池配置
    • WebClient

    • WebFlux

    • WebSocket

    • Web三剑客

    • 实例

    • 其他

  • 中间件

  • 运维

  • SpringSecurity

  • SpringCloud

  • Spring系列
  • WEB系列
  • RestTemplate
一灰灰
2020-07-10

【WEB系列】RestTemplate之文件上传

虽然在实际的项目中,借助RestTemplate来实现文件上传的机会不多(比如我已经开webclient的新坑了,才发现忘了这货...),但是这个知识点也还是有必要了解一下的,本文将简单介绍一下单个文件上传,多个文件上传的使用姿势

# I. 项目搭建

本项目基于SpringBoot 2.2.1.RELEASE + maven 3.5.3 + idea进行开发

# 1. pom依赖

核心pom依赖如下

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
1
2
3
4

# 2. Rest服务

提供两个简单的上传文件的接口,下面给出两种不一样的写法,效果差不多

/**
 * 文件上传
 *
 * @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);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 3. 上传文件

在Resource资源目录下,新建两个用于测试上传的文本文件,内容分别如下

文件1 test.txt:

hello 一灰灰
天气不错哦😝
1
2

文件2 test2.txt:

hello 二灰灰
天气还可以哦😝
1
2

简单设置一下日志格式,在application.yml文件中

logging:
  pattern:
    console: (%msg%n%n){blue}
1
2
3

# II. 项目实现

文件上传,依然是走的POST请求,所以基本操作知识和前面的POST差不多,唯一的区别在于传参

# 1. 文件上传

文件上传两个核心步骤

  • 设置请求头
  • 传参为Resource

最基础的单文件上传姿势实例如下,主要是借助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);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

当需要后端发起上传文件时,一般来讲是更多的情况下是上传二进制(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);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

重点注意

  • InputStreamResource 重写了contentLength(), getFilename()方法,去掉这个就没法正常的上传文件了

当然除了InputStreamResource之外,ByteArrayResource也是一个比较好的选择

ByteArrayResource byteArrayResource = new ByteArrayResource("hello 一灰灰😝".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);
1
2
3
4
5
6
7
8
9
10
11

重点注意

  • ByteArrayResource重写了getFilename()方法,感兴趣的小伙伴可以测试一下没有它的情况

# 2. 多文件上传

上面介绍的是单文件上传,当然我们也会出现一次上传多个文件的情况,使用姿势和前面基本上一样,无非是传参的时候多传两个而已

// 多个文件上传
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);
1
2
3
4
5
6
7
8
9
10
11
12
13

# 3. 输出结果

# II. 其他

# 0. 项目&系列博文

博文

  • 【WEB系列】AsyncRestTemplate之异步非阻塞网络请求介绍篇 (opens new window)
  • 【WEB系列】RestTemplate之非200状态码信息捕获 (opens new window)
  • 【WEB系列】RestTemplate之Basic Auth授权 (opens new window)
  • 【WEB系列】RestTemplate之代理访问 (opens new window)
  • 【WEB系列】RestTemplate之超时设置 (opens new window)
  • 【WEB系列】RestTemplate之中文乱码问题fix (opens new window)
  • 【WEB系列】RestTemplate之自定义请求头 (opens new window)
  • 【WEB系列】RestTemplate基础用法小结 (opens new window)

源码

  • 工程:https://github.com/liuyueyi/spring-boot-demo (opens new window)
  • 源码: https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-boot/221-web-resttemplate (opens new window)

# 1. 一灰灰Blog

尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

下面一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

  • 一灰灰Blog个人博客 https://blog.hhui.top (opens new window)
  • 一灰灰Blog-Spring专题博客 http://spring.hhui.top (opens new window)

一灰灰blog

编辑 (opens new window)
#RestTemplate
上次更新: 2021/10/15, 19:56:22
【WEB系列】AsyncRestTemplate之异步非阻塞网络请求介绍篇
【WEB系列】RestTemplate之连接池配置

← 【WEB系列】AsyncRestTemplate之异步非阻塞网络请求介绍篇 【WEB系列】RestTemplate之连接池配置→

最近更新
01
【基础系列】基于maven多环境配置
04-25
02
【WEB系列】内嵌Tomcat配置Accesslog日志文件生成位置源码探索
04-24
03
【搜索系列】ES查询常用实例演示
04-18
更多文章>
Theme by Vdoing | Copyright © 2017-2022 一灰灰Blog
MIT License | 鄂ICP备18017282号 |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×