.form文件_【SpringBoot WEB系列】RestTemplate之文件上传

697d0bd6a2912332d97ac351ec000f40.png

【SpringBoot WEB系列】RestTemplate之文件上传

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

I. 项目搭建

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

1. pom依赖

核心pom依赖如下

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>

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 files = request.getFiles("data");
    List ans = new ArrayList<>();for (MultipartFile file : files) {
        ans.add(new String(file.getBytes(), "utf-8"));
    }return JSON.toJSONString(ans);
}

3. 上传文件

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

文件1 test.txt:

hello 一灰灰
天气不错哦?

文件2 test2.txt:

hello 二灰灰
天气还可以哦?

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

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

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 form = new LinkedMultiValueMap<>();// post的文件
form.add("data", fileSystemResource);// post的表单参数
form.add("name", "哒哒哒");//用HttpEntity封装整个请求报文
HttpEntity> 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 一灰灰?".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()方法,感兴趣的小伙伴可以测试一下没有它的情况

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);

3. 输出结果

741561d15c0fdd147bb9644a1ce3dc9e.png

II. 其他

0. 项目&系列博文

博文

  • 【SpringBoot WEB 系列】AsyncRestTemplate 之异步非阻塞网络请求介绍篇

  • 【SpringBoot WEB 系列】RestTemplate 之非 200 状态码信息捕获

  • 【SpringBoot WEB 系列】RestTemplate 之 Basic Auth 授权

  • 【SpringBoot WEB 系列】RestTemplate 之代理访问

  • 【SpringBoot WEB 系列】RestTemplate 之超时设置

  • 【SpringBoot WEB 系列】RestTemplate 之中文乱码问题 fix

  • 【SpringBoot WEB 系列】RestTemplate 之自定义请求头

  • 【SpringBoot WEB 系列】RestTemplate 基础用法小结

  • 【SpringBoot WEB 系列】RestTemplate 4xx/5xx 异常信息捕获

  • 【SpringBoot WEB 系列】RestTempalte urlencode参数解析异常全程分析

源码

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

1. 一灰灰Blog

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

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

  • 一灰灰Blog个人博客 https://blog.hhui.top
  • 一灰灰Blog-Spring专题博客 http://spring.hhui.top
707bb41121d7a89015d4dab5d549f9b7.png
一灰灰blog
文件分片上传是一种常见的上传大文件的方式,可以将大文件分成多个小文件进行上传,提高上传速度和稳定性。Springboot提供了restTemplate来方便地进行HTTP请求,可以使用restTemplate实现文件分片上传到第三方接口。 下面是一个简单的示例,用于将一个大文件分成多个小文件进行上传: 1.首先,需要确定每个文件分片的大小,以及总的分片数。可以使用文件长度和分片大小来计算总的分片数。 2.使用restTemplate发送HTTP请求,将每个分片上传到第三方接口。可以使用MultiValueMap来设置HTTP请求参数,包括文件分片数据和其他参数。 3.在上传完成后,将所有分片上传的结果合并起来,判断是否上传成功。 以下是一个简单的示例代码: ```java public class FileUploadService { private RestTemplate restTemplate; public void uploadFile(String url, File file, int chunkSize) { long fileSize = file.length(); int totalChunks = (int) Math.ceil(fileSize / (double) chunkSize); String filename = file.getName(); String contentType = Files.probeContentType(file.toPath()); for (int chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) { int start = chunkIndex * chunkSize; int end = (int) Math.min(start + chunkSize, fileSize); byte[] chunkData = Files.readAllBytes(file.toPath()).subList(start, end).toArray(new byte[0]); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); body.add("file", new ByteArrayResource(chunkData) { @Override public String getFilename() { return filename; } }); body.add("filename", filename); body.add("contentType", contentType); body.add("chunkIndex", chunkIndex); body.add("totalChunks", totalChunks); HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers); ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); // handle response if (responseEntity.getStatusCode() != HttpStatus.OK) { throw new RuntimeException("File upload failed: " + responseEntity.getBody()); } } } } ``` 在上面的代码中,我们使用了ByteArrayResource来表示文件分片的数据,同时设置了HTTP请求的其他参数,包括文件名、文件类型、分片索引和总的分片数。在上传完成后,我们可以根据所有分片上传的结果来判断上传是否成功。 请注意,上面的代码仅作为示例。实际使用时,还需要处理上传中可能出现的异常和错误情况,以及进行适当的重试和恢复操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值