工具篇--Spring-Cloud--feign 通过feign 接口完成文件的下载

文章目录

  • 前言
  • 一、feign接口获取文件流程:
  • 二、文件获取实现
    • 2.1 引入jar:
    • 2.2 实现:
  • 总结


前言

通常在spring-boot 项目中,对于文件的下载都是直接调用到对应的服务中,而不是通过feign 接口获取文件;有时我们在对接外部接口时,因为权限等问题,不能直接暴露文件服务,会有一个专门对外的服务进行对接,但是我们又要利用现有的文件服务逻辑,此时可以考虑使用feign 完成文件的获取。


一、feign接口获取文件流程:

我们知道feign 只是通过动态代理为我们构建了http 的请求,显然我们不能通过feign 接口直接把 HttpServletResponse 传过去,因为feign接口服务的提供者,接收到的HttpServletResponse 和我们通过feign 接口传入的压根儿就不是同一个对象,所以此时我们只能在文件服务中返回文件流,然后在将文件流 写入到最开始HttpServletResponse 对象中,最后返回给浏览器,流程大概如下:
在这里插入图片描述

二、文件获取实现

2.1 引入jar:

因为我们是web 服务并且使用了feign 接口所有这个两个jar 依赖是必须要有的:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2.2 实现:

(1) feign 接口:

@GetMapping(value = "/osp/download/{id}", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
ResponseEntity<Resource> download(@PathVariable("id") String id);

(2)feign 接口服务提供者:
控制器:

import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;@GetMapping("/osp/download/{id}")public ResponseEntity<Resource> ospDownloadFile(@PathVariable String id) throws Exception {return xxxService.ospDownloadFile(id);}

xxxService 对应自己业务里面的实现;实现类:

 @Override
public ResponseEntity<org.springframework.core.io.Resource> ospDownloadFile(String id) throws Exception {// 这里获取自己业务中的文件FileRecord fileRecord = fileRecordService.selectCache(id);if (null == fileRecord)throw new Exception("文件不存在");InputStream inputStream = null;ByteArrayOutputStream outputStream = null;try {inputStream = getObjectInputStream(fileRecord.getCodeName());outputStream = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int length;while ((length = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, length);}byte[] byteArray = outputStream.toByteArray();// 读取文件内容ByteArrayResource resource = new ByteArrayResource(byteArray);// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" +  java.net.URLEncoder.encode(fileRecord.getName(),"UTF-8"));// 返回响应实体return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_OCTET_STREAM).body(resource);} finally {if (null != inputStream) {inputStream.close();}if (null != outputStream) {outputStream.close();}}}

(3)对外服务端:
对外服务控制器:

@GetMapping("/file/download/{id}")
public void download(@PathVariable String id,HttpServletResponse response) throws Exception {ospFlowService.ospDownLoadFile(id,response);
}

业务实现类:

 @Override
public void ospDownLoadFile(String id,  HttpServletResponse response) throws Exception {// feign 接口获取文件流ResponseEntity<Resource> fileResponse = remoteFileService.download(id);// 设置响应头response.setHeader(HttpHeaders.CONTENT_DISPOSITION, fileResponse.getHeaders().get(HttpHeaders.CONTENT_DISPOSITION).get(0));response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);// 从 Feign 响应中获取文件输入流,并写入到 HttpServletResponse 输出流中InputStream inputStream = fileResponse.getBody().getInputStream();OutputStream output = response.getOutputStream();IoUtil.copy(inputStream, output);// 将流刷新给到浏览器response.flushBuffer();}

这里使用cn.hutool.core.io 中的 IoUtil 工具类,有需要的可以引入

 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId>
</dependency>

总结

本文通过feign 接口完成文件的下载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/317401.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高压功率放大器的作用或应用领域是什么

高压功率放大器是一种能够将低电压信号放大到高电压水平的设备。它在各个领域中扮演着重要的角色&#xff0c;并具有广泛的应用。本文将介绍高压功率放大器的作用和应用领域。 高压功率放大器可以在音频设备中发挥重要作用。音频设备中需要将低音频信号放大到足够的水平&#x…

使用python快速开发与PDF文档对话的Gemini聊天机器人

检索增强生成(Retrieval-augmented generation&#xff0c;RAG)使得我们可以让大型语言模型(LLMs)访问外部知识库数据(如pdf,word、text等)&#xff0c;从而让人们可以更加方便的通过LLM来学习外部数据的知识。今天我们将利用之前学习到的RAG方法&#xff0c;谷歌Gemini模型和l…

管程-第三十三天

目录 为什么要引入管程 管程的定义和基本特征 用管程解决生产者消费者问题 结论 本节思维导图 为什么要引入管程 原因&#xff1a;在解决进程的同步与互斥问题时&#xff0c;信号量机制存在编写困难和易出错的问题 能不能设计一种机制&#xff0c;让程序员写程序时不再需…

MySQL常见面试题总结

1.MySQL基础 1.1什么是关系型数据库&#xff1f; 顾名思义&#xff0c;关系型数据库&#xff08;RDB&#xff0c;Relational Database&#xff09;就是一种建立在关系模型的基础上的数据库。关系模型表明了数据库中所存储的数据之间的联系&#xff08;一对一、一对多、多对多…

.NET国产化改造探索(一)、VMware安装银河麒麟

随着时代的发展以及近年来信创工作和…废话就不多说了&#xff0c;这个系列就是为.NET遇到国产化需求的一个闭坑系列。接下来&#xff0c;看操作。 安装银河麒麟 麒麟系统分银河麒麟和中标麒麟&#xff0c;我选择的是银河麒麟服务器版的&#xff0c;关于如何下载&#xff0c;…

php ext-sodium 拓展安装 linux+windows

php编译安装(linux)&#xff0c;可以参考&#xff1a;php编译安装 一、windows soduim源码包自带&#xff0c;直接修改php.ini&#xff0c;取消extensionsodium注释即可 二、linux 1.安装依赖 apt-get install libsodium-dev2.进入源码目录 这里写自己的源码目录 cd /us…

YOLOv8改进 更换轻量化模型MobileNetV3

一、MobileNetV3论文 论文地址&#xff1a;1905.02244.pdf (arxiv.org) 二、 MobileNetV3网络结构 MobileNetV3引入了一种新的操作单元&#xff0c;称为"Mobile Inverted Residual Bottleneck"&#xff0c;它由一个1x1卷积层和一个3x3深度可分离卷积层组成。这个操…

Java基础-----集合类(二)

文章目录 1. 泛型简介2. 使用泛型的好处3.使用泛型3.1 泛型类3.2 泛型接口3.3 泛型方法 4 泛型的通配符4.1 <?>&#xff1a;无边界的通配符4.2 <? extends E>&#xff1a;固定上边界的通配符4.3 <? super E>&#xff1a;固定下边界的通配符 5.总结 今天主…

【React】class组件生命周期函数的梳理和总结(第一篇)

1. 前言 本篇梳理和总结一下React的生命周期函数&#xff0c;方便使用class组件的同学查阅&#xff0c;先上生命周期图谱。 2. 生命周期函数 生命周期函数说明constructor(props) 功能&#xff1a;如果不需要初始化state或不进行方法绑定&#xff0c;class组件可以不用实现构造…

【华为机试】2023年真题B卷(python)-考古问题

一、题目 题目描述&#xff1a; 考古问题&#xff0c;假设以前的石碑被打碎成了很多块&#xff0c;每块上面都有一个或若干个字符&#xff0c;请你写个程序来把之前石碑上文字可能的组合全部写出来&#xff0c;按升序进行排列。 二、输入输出 三、示例 示例1: 输入输出示例仅供…

BLE协议—协议栈基础

BLE协议—协议栈基础 BLE协议栈基础通用访问配置文件层&#xff08;Generic Access Profile&#xff0c;GAP&#xff09;GAP角色设备配置模式和规程安全模式广播和扫描 BLE协议栈基础 蓝牙BLE协议栈包含三部分&#xff1a;主机、主机接口层和控制器。 主机&#xff1a;逻辑链路…

resetlogs失败故障恢复-ORA-01555---惜分飞

客户数据库resetlogs报错 Tue Dec 19 15:21:23 2023 ALTER DATABASE MOUNT Successful mount of redo thread 1, with mount id 1683789043 Database mounted in Exclusive Mode Lost write protection disabled Completed: ALTER DATABASE MOUNT Tue Dec 19 15:22:01 2023…