热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

携带参数_SpringFeign携带复杂参数,进行文件上传

网上百度了很多办法均太过简单,大多都是携带几个简单的参数和一个File对象,如果将File和其他参数封装到一个对象或者DTO内就不行了网上的例子MultipartFileFeign

网上百度了很多办法均太过简单,大多都是携带几个简单的参数和一个File对象,如果将File和其他参数封装到一个对象或者DTO内就不行了

网上的例子 MultipartFile

Feign 无法直接传递文件参数,需要在client端引入几个依赖

io.github.openfeign.form:feign-form:3.0.3

io.github.openfeign.form:feign-form-spring:3.0.3

1. 创建服务端

方式与普通的文件上传方法一致

@RestController@RequestMapping("/producer/upload")class UploadProducer { @PostMapping(value = '/upload', consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) String upload(@RequestPart(value = "file") MultipartFile file) { // ... return file.originalFilename }}

2. 创建client

2.1 需要在客户端引入以下依赖

io.github.openfeign.form:feign-form:3.0.3io.github.openfeign.form:feign-form-spring:3.0.3

2.2 定义client接口

@FeignClient(name = 'upload', url = '${upload.base-url}', path = '/producer/upload')interface UploadClient { @RequestMapping(value = '/upload', method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE , produces = MediaType.APPLICATION_JSON_VALUE) String upload(@RequestPart("file") MultipartFile file)}

2.3 添加配置文件

划重点

@Configurationclass MultipartSupportConfig { @Autowired private ObjectFactory messageConverters // new一个form编码器,实现支持form表单提交 @Bean Encoder feignFormEncoder() { return new SpringFormEncoder(new SpringEncoder(messageConverters)) }}

3. 创建Controller,调用client接口

@RestController@RequestMapping("/")class RecordController { @Autowired private UploadClient uploadClient @RequestMapping(value = '/upload', method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE) String upload(@RequestParam("file") MultipartFile file) { return uploadClient.uploade(file) }}

可以看到网上的例子只能传递简单的表单参数 下面我有种需求 如果携带一个对象呢? 对象信息如下

package com.smdk.dsminio.vo; import lombok.Data;import lombok.ToString;import org.springframework.web.multipart.MultipartFile;import java.io.Serializable; /** * @author 神秘的凯 *date 2020-03-17 17:16 */@Data@ToStringpublic class MultipartFileParam implements Serializable { public static final long serialVersionUID=1L; // 用户id private String uid; //任务ID private String id; //总分片数量 private int chunks; //当前为第几块分片 private int chunk; //当前分片大小 private long size = 0L; //文件名 private String name; //分片对象 private MultipartFile file; // MD5 private String md5; //BucketID private Long bucketId; //文件夹ID private Long parentFolderId;}

如果这样直接上传Spring的解析器解析不到MultipartFileParam 自定义对象会直接报错 另外Spring只能解析自带的Multipart 对象

报错信息

%s is not a type supported by this encoder.....省略

那么如果传递自定义的参数对象呢 那就是重写Spring的对象解析器 代码如下

Feign 调用端代码

package com.smdk.dsminio.apiservice;import com.smdk.dsminio.config.FeignSupportConfig;import com.smdk.dsminio.utils.AjaxResult;import com.smdk.dsminio.vo.MultipartFileParam;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.http.MediaType;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod; @FeignClient(value = "OSS-STORAGE-SERVICE",configuration = FeignSupportConfig.class)public interface FileService { /** * produces 用于指定返回类型为JSON格式 * consumes 用于指定生产者数据请求类型 * @param multipartFileParam * @return */ @RequestMapping(value = "//OSS-STORAGE-SERVICE-$SERVER_ID/api/uploadFileInfo", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE},consumes = MediaType.MULTIPART_FORM_DATA_VALUE,method = RequestMethod.POST) AjaxResult uploadFileInfo(MultipartFileParam multipartFileParam);}

服务端

package com.smdk.dsminio.controller; import cn.hutool.log.StaticLog;import com.smdk.dsminio.redis.RedisUtil;import com.smdk.dsminio.service.FileStorageService;import com.smdk.dsminio.utils.AjaxResult;import com.smdk.dsminio.utils.Constants;import com.smdk.dsminio.vo.MultipartFileParam;import org.apache.commons.fileupload.servlet.ServletFileUpload;import org.apache.commons.io.FileUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;import org.springframework.http.MediaType;import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest;import java.io.File;import java.io.IOException;import java.util.LinkedList;import java.util.List; /** * 默认控制层 * Created by 神秘的凯 on 22020/11/11. * version 1.0 */@RestController@RequestMapping(value = "/api")public class FileDiskStorageController { @Autowired private FileStorageService fileStorageService; /** * 上传文件 * * @param param * @param request * @return * @throws Exception */ @RequestMapping(value = "/uploadFileInfo", method = RequestMethod.POST) public AjaxResult uploadFileInfo(MultipartFileParam multipartFileParam) { StaticLog.info("上传文件start。"); try { // 方法1 //storageService.uploadFileRandomAccessFile(param); // 方法2 这个更快点 boolean uploadResult= fileStorageService.uploadFileByMappedByteBuffer(multipartFileParam); if (uploadResult){ return AjaxResult.success(uploadResult,"上传完毕"); }else { return AjaxResult.fail("分片上传中...正在上传第"+multipartFileParam.getChunk()+"块文件块,剩余"+(multipartFileParam.getChunks()-multipartFileParam.getChunk())+"个分块"); } } catch (IOException e) { e.printStackTrace(); StaticLog.error("文件上传失败。{}", multipartFileParam.toString()); return AjaxResult.fail("文件上传失败"); } }}

核心重写feignFormEncoder 方法类 下面的的路由配置请忽略

package com.smdk.dsminio.config; import com.smdk.dsminio.vo.MultipartFileParam;import feign.Request;import feign.RequestInterceptor;import feign.RequestTemplate;import feign.codec.EncodeException;import feign.codec.Encoder;import feign.form.spring.SpringFormEncoder;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Primary;import org.springframework.context.annotation.Scope;import java.io.IOException;import java.lang.reflect.Type; import static java.lang.String.format;public class FeignSupportConfig{ //转换参数请求模型封装 @Bean @Primary @Scope("prototype") public Encoder feignFormEncoder() { return new SpringFormEncoder(new Encoder() { @Override public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException { if (bodyType == String.class) { template.body(Request.Body.bodyTemplate(object.toString(),null)); } else if (bodyType == byte[].class) { template.body(Request.Body.encoded((byte[]) object,null)); }else if (bodyType == MultipartFileParam.class) { MultipartFileParam multipartFileParam = (MultipartFileParam) object; try { template.body(Request.Body.encoded(multipartFileParam.getFile().getBytes(),null)); } catch (IOException e) { e.printStackTrace(); } } else if (object != null) { throw new EncodeException(format("%s is not a type supported by this encoder.", object.getClass())); } } }); } @Bean public feign.Logger.Level multipartLoggerLevel() { return feign.Logger.Level.FULL; } //路由重构 @Bean public RequestInterceptor cloudContextInterceptor() { return new RequestInterceptor() { @Override public void apply(RequestTemplate template) { String url = template.url(); if (url.contains("$SERVER_ID")) { url = url.replace("$SERVER_ID", route(template)); template.uri(url); } if (url.startsWith("//")) { url = "http:" + url; template.target(url); template.uri(""); } } private CharSequence route(RequestTemplate template) { // TODO 你的路由算法在这里 return "01"; } }; }}

可以看到我加了个判断 if (bodyType == MultipartFileParam.class) 进行自己封装的对象解析

大工告成 另外说下这个问题 品读了Spring的源码才搞定的 在此之前各种尝试和百度已经测试过无数前辈提供的方法 搞了两天才搞定这个bug 哎! 两天啊!!!!!!!!!!!!

245627afc8b690d050e404d751f3f2b4.png

作者:神秘的凯

原文链接:https://fujiakai.blog.csdn.net/article/details/109821141




推荐阅读
  • 图像因存在错误而无法显示 ... [详细]
  • 本文介绍了使用FormData对象上传文件同时附带其他参数的方法。通过创建一个表单,将文件和参数添加到FormData对象中,然后使用ajax发送POST请求进行文件上传。在发送请求时,需要设置processData为false,告诉jquery不要处理发送的数据;同时设置contentType为false,告诉jquery不要设置content-Type请求头。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • AFNetwork框架(零)使用NSURLSession进行网络请求
    本文介绍了AFNetwork框架中使用NSURLSession进行网络请求的方法,包括NSURLSession的配置、请求的创建和执行等步骤。同时还介绍了NSURLSessionDelegate和NSURLSessionConfiguration的相关内容。通过本文可以了解到AFNetwork框架中使用NSURLSession进行网络请求的基本流程和注意事项。 ... [详细]
  • fileuploadJS@sectionscripts{<scriptsrc~Contentjsfileuploadvendorjquery.ui.widget.js ... [详细]
  • 用ESP32与Python实现物联网(IoT)火焰检测报警系统
    下图是本案例除硬件连线外的3步导学开发过程,每个步骤中实现的功能请参考图中的说明。在硬件连线完成之后我们建议您先使用“一分钟上云体验”功能预先体验本案例的实际运行效果 ... [详细]
  • 原文转自:http:blog.csdn.netchinasoftosgarticledetails7903045UploadAction.java:packagecr ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • Java大文件HTTP断点续传到服务器该怎么做?
    最近由于笔者所在的研发集团产品需要,需要支持高性能的大文件http上传,并且要求支持http断点续传。这里在简要归纳一下,方便记忆 ... [详细]
  • 开发笔记:UEditor调用上传图片上传文件等模块
    1、引入ue相关文件,写好初始代码为了更好的封装整一个单独的插件,这里我们要做到示例化ue后隐藏网页中的编辑窗口,并移除焦点。 ... [详细]
author-avatar
青藤摄影876
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有