使用springcloud Fegin上传文件报错Could not write request: no suitable HttpMessageConverter found for request

 

一、问题简介

在springcloud微服务中,需要用到feign去调用文件上传的服务,如通过fastdfs文件服务器上传文件:

1、fegin的接口配置(服务降级代码:略~)

@FeignClient(value = "XXXXXXXX-XXXXX-PROVIDER", fallbackFactory = XxxxxxClientFallbackFactory.class)
public interface XxxxxxClientService {
    /**
     * 保存图片
     *
     * @param file
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/xxxxx/xxxxx/saveFile", method = RequestMethod.POST, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Result saveFile(@RequestPart("file") MultipartFile file) throws Exception;
}

 2、服务入口代码:

    /**
     * 保存文件
     *
     * @param file
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/xxxxx/xxxxx/saveFile", method = RequestMethod.POST, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Result saveFile(@RequestPart("file") MultipartFile file) throws Exception {
        try {
            return xxxxxxClientService.saveFile(file);//fegin接口服务调用
        } catch (Exception e) {
            log.error("~~~~", e);
        }
        return Result.error();

    }

3、文件上传服务(单独访问该服务,上传文件成功~) 

@RequestMapping(value = "/xxxxxx/saveFile", method = RequestMethod.POST)
    public Result saveFile(@RequestPart("file") MultipartFile file) throws Exception {
        if (file == null) {
            return new Result().put("code", "900001").put("msg", "对不起,文件保存失败").put("imgUrl", "");
        } else {
            String imgUrl = dfsClient.uploadFile(file); //利用fastdfs上传文件
            return new Result().put("code", "0").put("msg", "文件保存成功").put("imgUrl", imgUrl);
        }
    }

4、FastDFS文件服务器配置:(依赖、配置等略)

import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.exception.FdfsUnsupportStorePathException;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.Charset;


@Component
public class FastDFSClientWrapper {

    private static final Logger log = LoggerFactory.getLogger(FastDFSClientWrapper.class);

    @Autowired
    private FastFileStorageClient storageClient;

    @Value("${fdfs.resHost}")
    private String resHost;

    @Value("${fdfs.storagePort}")
    private String storagePort;

    /**
     * 上传文件
     *
     * @param file 文件对象
     * @return 文件访问地址
     * @throws IOException
     */
    public String uploadFile(MultipartFile file) throws IOException {
        StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()), null);
        return getResAccessUrl(storePath);
    }

    /**
     * 将一段字符串生成一个文件上传
     *
     * @param content       文件内容
     * @param fileExtension
     * @return
     */
    public String uploadFile(String content, String fileExtension) {
        byte[] buff = content.getBytes(Charset.forName("UTF-8"));
        ByteArrayInputStream stream = new ByteArrayInputStream(buff);
        StorePath storePath = storageClient.uploadFile(stream, buff.length, fileExtension, null);
        return getResAccessUrl(storePath);
    }

    // 封装图片完整URL地址
    private String getResAccessUrl(StorePath storePath) {
        String fileUrl = "http://" + resHost
                + ":" + storagePort + "/" + storePath.getFullPath();
        return fileUrl;
    }

    /**
     * 删除文件
     *
     * @param fileUrl 文件访问地址
     * @return
     */
    public void deleteFile(String fileUrl) {
        if (StringUtils.isEmpty(fileUrl)) {
            return;
        }
        try {
            StorePath storePath = StorePath.praseFromUrl(fileUrl);
            storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
        } catch (FdfsUnsupportStorePathException e) {
            log.warn(e.getMessage());
        }
    }

}

通过入口服务访问,会出现报错如下:

Caused by: feign.codec.EncodeException: Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile] and content type [multipart/form-data]
	at org.springframework.cloud.netflix.feign.support.SpringEncoder.encode(SpringEncoder.java:113) ~[spring-cloud-netflix-core-1.3.1.RELEASE.jar:1.3.1.RELEASE]
	at feign.ReflectiveFeign$BuildEncodedTemplateFromArgs.resolve(ReflectiveFeign.java:351) ~[feign-core-9.5.0.jar:na]
	at feign.ReflectiveFeign$BuildTemplateByResolvingArgs.create(ReflectiveFeign.java:213) ~[feign-core-9.5.0.jar:na]
	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:72) ~[feign-core-9.5.0.jar:na]
	at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java:108) ~[feign-hystrix-9.5.0.jar:na]
	at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:302) ~[hystrix-core-1.5.12.jar:1.5.12]
	at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:298) ~[hystrix-core-1.5.12.jar:1.5.12]
	at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46) ~[rxjava-1.1.10.jar:1.1.10]
	... 26 common frames omitted

解决办法:

1、pom.xml中添加依赖:


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

2、添加配置类:

import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;


@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;
    }
}

3、再通过fegin的方式去调用上传文件的服务:

{"msg":"文件保存成功","fileUrl":"http://xxx.xxx.xxx.xxx/group1/M00/00/00/Co1uzFzWlz6AZWC2AAltu9tu2nA760.png","code":"0"}

希望能解决路过人的问题。

新手一枚,欢迎拍砖~ ~ ~

你可能感兴趣的:(springboot)