本文是精讲RestTemplate第6篇,前篇的blog访问地址如下:

RestTemplate是HTTP客户端库,所以为了使用RestTemplate进行文件上传和下载,需要我们先编写服务端的支持文件上传和下载的程序。请参考我之前写的一篇文章:SpringBoot实现本地存储文件上传及提供HTTP访问服务 。按照此文完成学习之后,可以获得

  • 一个以访问服务URI为"/upload”的文件上传服务端点
  • 服务端点上传文件成功后会返回一个HTTP连接,可以用来下载文件。

下面我们就开始学习使用RestTemplate是HTTP客户端库,进行文件的上传与下载。

一、文件上传

写一个单元测试类,来完成RestTemplate文件上传功能,具体实现细节参考代码注释

@SpringBootTest
class UpDownLoadTests { @Resource
private RestTemplate restTemplate; @Test
void testUpload() {
// 文件上传服务上传接口
String url = "http://localhost:8888/upload";
// 待上传的文件(存在客户端本地磁盘)
String filePath = "D:\\data\\local\\splash.png"; // 封装请求参数
FileSystemResource resource = new FileSystemResource(new File(filePath));
MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
param.add("uploadFile", resource); //服务端MultipartFile uploadFile
//param.add("param1", "test"); //服务端如果接受额外参数,可以传递 // 发送请求并输出结果
System.out.println("--- 开始上传文件 ---");
String result = restTemplate.postForObject(url, param, String.class);
System.out.println("--- 访问地址:" + result);
} }

输出结果如下:

--- 开始上传文件 ---
--- 访问地址:http://localhost:8888/2020/08/12/028b38f1-3f9b-4088-9bea-1af8c18cd619.png

文件上传之后,可以通过上面的访问地址,在浏览器访问。或者通过RestTemplate客户端进行下载。

二、文件下载

执行下列代码之后,被下载文件url,会被正确的保存到本地磁盘目录targetPath。

@Test
void testDownLoad() throws IOException {
// 待下载的文件地址
String url = "http://localhost:8888/2020/08/12/028b38f1-3f9b-4088-9bea-1af8c18cd619.png";
ResponseEntity<byte[]> rsp = restTemplate.getForEntity(url, byte[].class);
System.out.println("文件下载请求结果状态码:" + rsp.getStatusCode()); // 将下载下来的文件内容保存到本地
String targetPath = "D:\\data\\local\\splash-down.png";
Files.write(Paths.get(targetPath), Objects.requireNonNull(rsp.getBody(),
"未获取到下载文件"));
}

这种下载方法实际上是将下载文件一次性加载到客户端本地内存,然后从内存将文件写入磁盘。这种方式对于小文件的下载还比较适合,如果文件比较大或者文件下载并发量比较大,容易造成内存的大量占用,从而降低应用的运行效率。

三、大文件下载

这种下载方式的区别在于

  • 设置了请求头APPLICATION_OCTET_STREAM,表示以流的形式进行数据加载
  • RequestCallback 结合File.copy保证了接收到一部分文件内容,就向磁盘写入一部分内容。而不是全部加载到内存,最后再写入磁盘文件。
@Test
void testDownLoadBigFile() throws IOException {
// 待下载的文件地址
String url = "http://localhost:8888/2020/08/12/028b38f1-3f9b-4088-9bea-1af8c18cd619.png";
// 文件保存的本地路径
String targetPath = "D:\\data\\local\\splash-down-big.png";
//定义请求头的接收类型
RequestCallback requestCallback = request -> request.getHeaders()
.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
//对响应进行流式处理而不是将其全部加载到内存中
restTemplate.execute(url, HttpMethod.GET, requestCallback, clientHttpResponse -> {
Files.copy(clientHttpResponse.getBody(), Paths.get(targetPath));
return null;
});
}

欢迎关注我的博客,里面有很多精品合集

  • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客

觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

精讲RestTemplate第6篇-文件上传下载与大文件流式下载的更多相关文章

  1. 精讲RestTemplate第7篇-自定义请求失败异常处理

    本文是精讲RestTemplate第7篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...

  2. 精讲RestTemplate第8篇-请求失败自动重试机制

    本文是精讲RestTemplate第8篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...

  3. 精讲RestTemplate第9篇-如何通过HTTP Basic Auth认证

    本文是精讲RestTemplate第9篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...

  4. 精讲RestTemplate第10篇-使用代理作为跳板发送请求

    本文是精讲RestTemplate第10篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层 ...

  5. 精讲RestTemplate第3篇-GET请求使用方法详解

    本文是精讲RestTemplate第3篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...

  6. 精讲RestTemplate第4篇-POST请求方法使用详解

    本文是精讲RestTemplate第4篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...

  7. 精讲RestTemplate第4篇-DELETE、PUT等请求方法使用详解

    本文是精讲RestTemplate第5篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...

  8. 精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换

    本文是精讲RestTemplate第2篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 RestTemplate只是对其他的HTTP客 ...

  9. php 文件上传后缀名与文件类型对照表(几乎涵盖所有文件)

    网上有很多php文件上传的类,文件上传处理是php的一个特色(至少手册上是将此作为php特点来展示的,个人认为php在数组方面的优异功能更有特 色),学php的人都知道文件上传怎么做,但很多人在编程中 ...

随机推荐

  1. echarts 实战 : 想让图例颜色和元素颜色对应,怎么办?

    首先,在 series 里设置颜色. (我是用js生成 echarts 需要的option对象,所以可能很难看懂) normalData.sData.forEach((item, index) =&g ...

  2. 题解 洛谷 P4695 【[PA2017]Banany】

    考虑用动态点分治来解决像本题这样带修的树上路径问题. 首先对原树进行点分治,建出点分树,在点分树每个节点上用动态开点线段树来维护以该节点为起点,到其点分树子树中每个节点的利润. 查询时只需在点分树上当 ...

  3. 题解 洛谷 P3340 【[ZJOI2014]星系调查】

    根据题意,发现题目中的图,其实就是一颗树或者是一颗基环树,每个节点上有一个点对\((x,y)\),每次询问为给定端点,找一条直线到端点间的所有点的距离之和最小. 设这条直线为\(y=kx+b\),根据 ...

  4. Vue脚手架创建项目出现 (Failed to download repo vuejs-templates/webpack: Response code 404)

    搭建好(脚手架2.X版本)环境像往常一样使用vue init webpack xxxx 创建项目可以是没多久就开始报错了 报错结果就是:vue-cli · Failed to download rep ...

  5. transaction already active

    这个问题是使用spring 事务管理时经常出现的错误,最开始时相当令我头疼,也不知道是哪里出现的问题.在网上找了一阵后,依然无解.意思就是说上一个事务处于激活状态中,不能开始新的数据库更新操作. // ...

  6. Django开发之Ajax 返回内容报错

    预期效果 Django通过Ajax POST提交数据,前台弹窗处理结果 粗略代码 # views.py 代码 ...省略... msg = { 'code': 200, 'message': 'Hel ...

  7. SUM and COUNT -- SQLZOO

    SUM and COUNT 注意:where语句中对表示条件的需要用单引号, 下面的译文使用的是有道翻译如有不正确,请直接投诉有道 01.Show the total population of th ...

  8. Flutter中的绘图(Canvas&CustomPaint)API

    本文是Flutter中Canvas和CustomPaint API的使用实例. 首先看一下我们要实现的效果: 结合动图演示,列出最终目标如下: 在程序运行后,显示一个小球: 每次程序启动后,小球的样式 ...

  9. PHP asXML() 函数

    实例 格式化 XML(版本 1.0)中的 SimpleXML 对象的数据: <?php$note=<<<XML<note>高佣联盟 www.cgewang.com& ...

  10. 代码规范、API设计等规范

    一份整理好了的规范文档,node后端开发用到 "规范是个好东西..." - 鲁迅 以下规范仅作为参考 1.代码规范 命名 尽量保证命名更加语义化 文件命名采用下划线命名法 // g ...