}
feign config
@Configuration
public class FeignMultipartSupportConfig {
@Bean
@Primary
@Scope(“prototype”)
public Encoder multipartFormEncoder() {
return new SpringFormEncoder();
}
@Bean
public feign.Logger.Level multipartLoggerLevel() {
return feign.Logger.Level.FULL;
}
}
maven
io.github.openfeign.form
feign-form
2.1.0
io.github.openfeign.form
feign-form-spring
2.1.0
也可以不引入maven
feign config
@Configuration
public class MultipartSupportConfig {
@Bean
@Primary
@Scope(“prototype”)
public Encoder multipartFormEncoder() {
return new SpringMultipartEncoder();
}
}
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class SpringMultipartEncoder implements Encoder {
private static final Charset DEFAULT_CHARSET = Charset.forName(“UTF-8”);
private static final Class MULTIPART_ARRAY_CLAZZ = MultipartFile.class;
private static final String FILES_KEY = “file”;
private final List<HttpMessageConverter<?>> converters = new RestTemplate().getMessageConverters();
private final HttpHeaders multipartHeaders = new HttpHeaders();
private final HttpHeaders jsonHeaders = new HttpHeaders();
/**
- Instantiates a new Spring multipart encoder.
*/
public SpringMultipartEncoder() {
multipartHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
jsonHeaders.setContentType(MediaType.APPLICATION_JSON);
}
/**
- {@inheritDoc }
*/
@Override
public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
if (isFormRequest(bodyType)) {
encodeMultipartFormRequest(object, template);
} else {
encodeRequest(object, jsonHeaders, template);
}
}
/**
-
Encodes the request as a multipart form. It can detect a single {@link MultipartFile}, an
-
array of {@link MultipartFile}s, or POJOs (that are converted to JSON).
-
@param object
-
@param template
-
@throws EncodeException
*/
private void encodeMultipartFormRequest(Object object, RequestTemplate template) throws EncodeException {
if (object == null) {
throw new EncodeException(“Cannot encode request with null form.”);
}
LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
if (isMultipartFile(object)) {
MultipartFile multipartFile = (MultipartFile) object;
map.add(multipartFile.getName(), encodeMultipartFile(multipartFile));
} else if (isMultipartFileArray(object)) {
encodeMultipartFiles(map, FILES_KEY, Arrays.asList((MultipartFile[]) object));
} else {
map.add(“”, encodeJsonObject(object));
}
encodeRequest(map, multipartHeaders, template);
}
private boolean isMultipartFile(Object object) {
return object instanceof MultipartFile;
}
private boolean isMultipartFileArray(Object o) {
return o != null && o.getClass().isArray() && MultipartFile.class.isAssignableFrom(o.getClass().getComponentType());
}
/**
-
Wraps a single {@link MultipartFile} into a {@link HttpEntity} and sets the
-
{@code Content-type} header to {@code application/octet-stream}
-
@param file
-
@return
*/
private HttpEntity<?> encodeMultipartFile(MultipartFile file) {
HttpHeaders filePartHeaders = new HttpHeaders();
filePartHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
try {
Resource multipartFileResource = new MultipartFileResource(file.getOriginalFilename(), file.getSize(), file.getInputStream());
return new HttpEntity(multipartFileResource, filePartHeaders);
} catch (IOException ex) {
throw new EncodeException(“Cannot encode request.”, ex);
}
}
/**
-
Fills the request map with {@link HttpEntity}s containing the given {@link MultipartFile}s.
-
Sets the {@code Content-type} header to {@code application/octet-stream} for each file.
-
@param map current request map.
-
@param name the name of the array field in the multipart form.
-
@param files
*/
private void encodeMultipartFiles(LinkedMultiValueMap<String, Object> map, String name, List<? extends MultipartFile> files) {
HttpHeaders filePartHeaders = new HttpHeaders();
filePartHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
try {
for (MultipartFile file : files) {
Resource multipartFileResource = new MultipartFileResource(file.getOriginalFilename(), file.getSize(), file.getInputStream());
map.add(name, new HttpEntity(multipartFileResource, filePartHeaders));
}
} catch (IOException ex) {
throw new EncodeException(“Cannot encode request.”, ex);
}
}
/**
-
Wraps an object into a {@link HttpEntity} and sets the {@code Content-type} header to
-
{@code application/json}
-
@param o
-
@return
*/
private HttpEntity<?> encodeJsonObject(Object o) {
HttpHeaders jsonPartHeaders = new HttpHeaders();
jsonPartHeaders.setContentType(MediaType.APPLICATION_JSON);
return new HttpEntity(o, jsonPartHeaders);
}
/**
-
Calls the conversion chain actually used by
-
{@link RestTemplate}, filling the body of the request
-
template.
-
@param value
-
@param requestHeaders
-
@param template
-
@throws EncodeException
*/
private void encodeRequest(Object value, HttpHeaders requestHeaders, RequestTemplate template) throws EncodeException {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
![img](https://img-blog.csdnimg.cn/img_convert/0e7cd15f7c549ea4dc3014f8dde22cda.jpeg)
面试准备+复习分享:
为了应付面试也刷了很多的面试题与资料,现在就分享给有需要的读者朋友,资料我只截取出来一部分哦
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
![img](https://img-blog.csdnimg.cn/img_convert/0e7cd15f7c549ea4dc3014f8dde22cda.jpeg)
面试准备+复习分享:
为了应付面试也刷了很多的面试题与资料,现在就分享给有需要的读者朋友,资料我只截取出来一部分哦
[外链图片转存中…(img-Hf1JQIus-1713298454357)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!