最近用springcloud上传文件,消费者端与服务提供端通过feign调用,中间稍微踩了点坑,现将最终可执行代码发布出来:
事先说明,这里 base64编码保存图片文件是个性需求,这些相关代码,各位可以忽略,只关注上传文件的相关代码便可。
如果改成页面传入base64编码或消费者端传入base64编码,则在feign与底层service接口直接用String 参数传递接收便可。
<!-- Feigh uploadFile-->
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form-spring</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>RELEASE</version>
</dependency>
版本依赖:springboot版本2.1.3.RELEASE版本,springcloud为GreenWich的最新版本
2.服务提供方各层代码实现类,这是转换成base64字节码保存到数据库的示例。
有些代码不是太完整
@Slf4j
@Service
@RestController
@Transactional(rollbackFor = Exception.class)
@Api(position = 22, tags = {"ApplicationService"}, description = "应用管理服务, 提供增删改查等操作的管理接口")
public class ApplicationServiceImpl implements ApplicationService {
@Autowired
private ApplicationDao applicationDao;
@Override
public String saveLogoById(@NonNull String id, @NonNull MultipartFile logo) {
if (StringUtils.isBlank(id)) {
throw new IllegalArgumentException("appId must be not empty.");
}
byte[] prefix="data:image/png;base64,".getBytes();
byte[] _logo = new byte[0];
try {
_logo= Base64.encodeBase64(logo.getBytes());
} catch (Exception e) {
throw new RuntimeException(e);
}
byte[] mylogo=new byte[prefix.length+_logo.length];
System.arraycopy(prefix, 0, mylogo, 0, prefix.length);
System.arraycopy(_logo, 0, mylogo, prefix.length, _logo.length);
applicationDao.logoSaveById(id, mylogo);
return id;
}
@Override
public ResponseEntity<byte[]> getLogoById(@NonNull String id) {
byte[] logo = ((ApplicationDao) this._getBaseDao()).logoGetById(id);
return new ResponseEntity<>(logo, HttpStatus.OK);
}
}
dao中之保存获取并无不同。
xml之写法
<update id="logoSave" parameterType="hashmap"> UPDATE ECS_APP SET APP_LOGO=#{logo},APP_UPDATED_AT = CURRENT_TIMESTAMP(3) WHERE APP_ID = #{id} </update>
3.若直接以base64编码后做为字符串传入,也是一样。
4.feign客户端接口:
@FeignClient(value = "ecs", contextId = "ApplicationService" ,configuration = FeignMultipartSupportConfig.class)
@RequestMapping(value = "/ApplicationService")
public interface ApplicationService {
@PostMapping(value = "/saveLogoById",produces = {MediaType.APPLICATION_JSON_VALUE}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ApiOperation(position = 62, value = "保存指定ID应用的商标", notes = "如果保存不成功, 抛出异常")
@ApiImplicitParams(value = {
@ApiImplicitParam(paramType = "query", name = "id", required = true, dataType = "string", value = "应用ID"),
//这里没logo的
})
String saveLogoById(@ApiIgnore @NonNull @RequestParam(value = "id") String id, @ApiIgnore @NonNull @RequestPart(value = "logo") MultipartFile logo);
@PostMapping(value = "/getLogoById", produces = {MediaType.APPLICATION_JSON_VALUE})
@ApiOperation(position = 61, value = "获取指定ID应用的商标", produces = MediaType.APPLICATION_JSON_VALUE, notes = "如果获取成功, 返回商标, 无商标返回null, 如果应用不存在或其它原因, 则抛出异常")
@ApiImplicitParams(value = {
@ApiImplicitParam(paramType = "query", name = "id", required = true, dataType = "string", value = "应用ID"),
})
ResponseEntity<byte[]> getLogoById(@ApiIgnore @NonNull @RequestParam(value = "id") String id);
}
@FeignClient(value = "ecs", contextId = "ApplicationService" ,configuration = FeignMultipartSupportConfig.class) 这里的FeignMultipartSupportConfig类示例代码
import feign.codec.Encoder; import feign.form.spring.SpringFormEncoder; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.cloud.openfeign.support.SpringEncoder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FeignMultipartSupportConfig { @Autowired private ObjectFactory<HttpMessageConverters> messageConverters; @Bean public Encoder feignFormEncoder() { return new SpringFormEncoder(new SpringEncoder(messageConverters)); } @Bean public feign.Logger.Level multipartLoggerLevel() { return feign.Logger.Level.FULL; } }
5.消费者端测试代码:
@PostMapping(value = "/testLogo")
@ApiOperation(position = 62, value = "测试Logo",response = Map.class, notes = "如果保存不成功, 抛出异常")
public boolean testLogo(){
File file = new File("E:\\haha.png");
DiskFileItem fileItem = (DiskFileItem) new DiskFileItemFactory().createItem("logo",
MediaType.TEXT_PLAIN_VALUE, true, file.getName());
try (InputStream input = new FileInputStream(file);
OutputStream os = fileItem.getOutputStream()) {
IOUtils.copy(input, os);
} catch (Exception e) {
throw new IllegalArgumentException("Invalid file: " + e, e);
}
MultipartFile logo = new CommonsMultipartFile(fileItem);
log.info(applicationService.saveLogoById("20190520132707572-1007-CD574C23C",logo));
return true;
}
注意这里有个坑,createItem("logo",这里的名称一定要各feign里的参数名称 一样,否则调用时 feign无法传入此参数。消费者端logo参数无值。
6.消费者端正式代码:
@Slf4j @RestController @RequestMapping("/app") @Api(tags = {"ApplicationController"}, description = "应用管理服务")
@PostMapping(value = "/saveLogo") @ApiOperation(position = 62, value = "保存指定ID应用的商标", response = Map.class, notes = "如果保存不成功, 抛出异常") @ApiImplicitParams(value = { @ApiImplicitParam(paramType = "query", name = "appId", required = false, dataType = "string", value = "应用ID"), }) public String saveLogo(@RequestPart(value = "logo") MultipartFile logo, String appId) { if (StringUtils.isBlank(appId)) { Application application = new Application(); application.setName("onlysavelogo_"+RandomStringUtils.random(30)); application.setEntId(AccessIdentity.getEnterpriseId()); appId = applicationService.create(application); } return applicationService.saveLogoById(appId, logo); } @PostMapping(value = "/getLogoById") @ApiOperation(position = 61, value = "获取指定ID应用的商标", produces = MediaType.APPLICATION_JSON_VALUE, notes = "如果获取成功, 返回商标, 无商标返回null, 如果应用不存在或其它原因, 则抛出异常") @ApiImplicitParams(value = { @ApiImplicitParam(paramType = "query", name = "appId", required = true, dataType = "string", value = "应用ID") }) public ResponseEntity<byte[]> getLogoById(@NonNull String appId) { return applicationService.getLogoById(appId); }
}
同时传入图片与对象调用
@PostMapping(value = "/addApplicationInfo") @ApiOperation(position = 62, value = "保存应用完整信息(应用及图片)", response = Map.class, notes = "如果保存不成功, 抛出异常") @ApiImplicitParams(value = { // @ApiImplicitParam(paramType = "query", name = "appId", required = false, dataType = "string", value = "应用ID") }) public String addApplicationInfo(@RequestPart(value = "logo") MultipartFile logo,@NonNull ApplicationVo applicationVo) { //同时上传logo用这个代码 }
这里如此接收参数便可。
经测试是没有问题.
相关推荐
Spring Cloud Feign上传文件示例详解 本篇文章主要介绍了使用Spring Cloud Feign上传文件的示例,通过配置Feign Client和Encoder实现文件上传。下面是相关知识点的详细解释: 一、Feign Client配置 在使用Spring ...
Spring Cloud Feign 实现远程调用服务传输文件的方法 在微服务架构中,服务之间的调用和文件传输是非常常见的场景。Spring Cloud Feign 是一个基于 Java 的声明式 RESTful 客户端,提供了一种简单、可靠的方式来...
本话题主要探讨如何在Spring Cloud环境中处理文件上传,特别是在结合Feign和Zuul这两个组件时的实现方法。Feign是Spring Cloud的一个声明式HTTP客户端,用于简化服务间的调用;而Zuul则是作为API网关,提供路由、...
SpringCloud使用Feign文件上传、下载 在分布式系统中,文件上传和下载是非常常见的场景。SpringCloud提供了Feign来帮助我们实现文件上传和下载功能。在本文中,我们将详细介绍如何使用SpringCloud和Feign来实现文件...
Spring Cloud Feign 文件上传实现的示例代码 Spring Cloud Feign 是一个基于 Java 的微服务框架,提供了许多实用的功能,例如服务发现、负载均衡、熔断器等。但是,在默认情况下,Spring Cloud Feign 不支持文件...
服务提供者需要处理文件上传的请求,因此需要在 Controller 中编写上传文件的逻辑: ```java @ResponseBody @RequestMapping(value = "/upload", method = {RequestMethod.POST}, produces = {MediaType....
其次,服务间的调用在Spring Cloud中通常通过RestTemplate或Feign来实现。例如,user服务和order服务之间,可以通过调用对方的服务接口进行通信。Feign是一种声明式Web服务客户端,使得编写Web服务调用就像调用本地...
在SpringCloud生态系统中,Feign是一个非常重要的组件,它提供了声明式的服务调用方式,使得微服务间的通信变得更加简洁。然而,在实际应用中,我们可能会遇到一些“坑”,特别是当涉及到处理复杂请求体,如...
Spring Cloud 中 FeignClient 实现文件上传功能需要添加 feign-form 和 feign-form-spring 库,注入 SpringFormEncoder 类,并使用 @RequestPart 注解指定文件类型的参数。但是,需要解决文件数组类型不支持的问题,...
在SpringCloud框架中,文件上传和下载是常见的功能需求,特别是在构建微服务架构时。SpringCloudFileSvr可能是一个专门处理文件操作的服务,用于提供文件的上传、存储和下载等功能。下面将详细介绍如何在SpringCloud...
业务层:Spring IOC、Aop事务控制、Spring Task任务调度、Feign、Ribbon、Spring AMQP、Spring Data Redis等。 控制层:Spring MVC、FastJSON、RestTemplate、Spring Security Oauth2+JWT等 微服务治理:Eureka、...
Zuul也支持通过上传文件、禁用过滤器、设置Hystrix回退等功能。 在消息驱动方面,Spring Cloud Stream为消息中间件提供了统一的消息通信模式。它通过定义Binder抽象,提供持续发布-订阅、消费群体分区以及编程模型...
├36 6.8通过Zuul上传文件,禁用Zuul的Filters.avi ├37 6.9 Zuul的回退.avi ├38 6.10 使用Sidecar支持异构平台的微服务.avi ├39 6.10 Sidecar补充.avi ├4 服务提供者与服务消费者.avi ├4 服务提供者与服务消费...
- **通过Zuul上传文件**:提供了关于如何通过Zuul网关上传文件的具体指导。 - **查询字符串编码**:讨论了如何处理URL中的查询字符串编码问题。 - **普通嵌入Zuul**:解释了如何在非Spring Boot项目中嵌入Zuul。 ##...
文件结尾部分提到了如何通过Zuul上传文件,以及如何实现简单的嵌入式Zuul。此外,还讨论了如何禁用Zuul的过滤器,通过Sidecar进行多语言支持,以及如何将RxJava与Spring MVC集成。最后,文档提到了指标相关的...
开发时,可以将Base-service作为一个独立的模块,通过Spring Cloud的Feign客户端进行远程调用,实现服务间的通信。 Web端通常指的是前端应用程序,它负责用户界面展示和与后端服务的交互。可以使用React、Vue.js或...
SpringCloud并没有提供专门的文件上传解决方案,但可以通过集成如Spring Boot的MultipartFile处理文件上传,结合云存储服务如阿里云OSS或AWS S3实现分布式文件系统。 以上就是SpringCloud框架中的关键组件及其功能...
11. 路由和过滤器Zuul:解释了Zuul作为Spring Cloud中的边缘服务如何工作,包括如何嵌入Zuul、使用Zuul Http客户端、处理Cookie和敏感Header、定义路由、文件上传、查询字符串编码、禁用过滤器和提供Hystrix回退的...
基于Vue+SpringCloud博客的设计与实现---微服务基础版本组件1.0版本 博客采用Vue+SpringCloud前后分离的方式。博客采用了高可用Eureka(可以替换成其他微服务组件)以及高可用Zuul,使用以Es搜索引擎作为Zpkin的存储...
### Spring Cloud 电商项目知识点概览 #### 一、项目背景与概述 - **项目名称**:“Spring Cloud 电商项目” - **项目描述**:这是一个基于Spring Cloud的微服务电商系统,涵盖了完整的电商功能模块,如会员管理、...