feign文件上传

记录一下

feign文件上传

  • 环境
    • spring-boot 2.3.7
     <parent>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-parent</artifactId>
          <version>2.3.7.RELEASE</version>
          <relativePath/> <!-- lookup parent from repository -->
      </parent>
    
    • 依赖引入
     <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-openfeign</artifactId>
             <version>2.1.0.RELEASE</version>
         </dependency>
    
    • 网上版本的依赖
    <!-- Feign文件上传依赖-->
    <dependencies>
    <dependency>
     <groupId>io.github.openfeign.form</groupId>
     <artifactId>feign-form</artifactId>
     <version>3.8.0</version>
    </dependency>
    <dependency>
     <groupId>io.github.openfeign.form</groupId>
     <artifactId>feign-form-spring</artifactId>
     <version>3.8.0</version>
    </dependency>
    </dependencies>dependency>
    

    和你的feign依赖有关,自己判断下,2.1.0已经包含了在这里插入图片描述

配置文件

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;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;

@Configuration
public class FeignMultipartSupportConfig {
    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;
    @Bean
    @Primary
    @Scope("prototype")
    public Encoder multipartFormEncoder() {
        return new SpringFormEncoder(new SpringEncoder(messageConverters));
    }

    @Bean
    public feign.Logger.Level multipartLoggerLevel() {
        return feign.Logger.Level.FULL;

    }

}

feign接口

import com.alibaba.fastjson.JSONObject;
import com.zzg.web.config.FeignMultipartSupportConfig;
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;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;

/**
 * @program: atomic-upms
 * @description:
 * @author: zzg@xnj
 * @create: 2024-08-20 16:50
 **/
@FeignClient(value = "file-service", url = "${file-service}", configuration  = {FeignMultipartSupportConfig.class})
public interface FileFeign {


    @RequestMapping(value ="/file/fileUpload",method = RequestMethod.POST, consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    JSONObject fileupload(@RequestPart(value="uploadfile") MultipartFile uploadfile) ;
}

service

@Service
public class FileService {

    @Resource
    private FileFeign fileFeign;

    public void uploadFile(MultipartFile file) {
        fileFeign.fileupload(file);
    }
}

controller

注意两个接口的区别

@Api(tags = "文件")
@RestController
@RequestMapping("/file")
public class UploadController {
    @Resource
    private FileService fileService;



    @ApiOperation("上传文件")
    @PostMapping("/fileUpload")
    public ResponseModel uploadFile(@RequestPart MultipartFile uploadfile) {


        fileService.uploadFile(uploadfile);

        return new ResponseModel("200","ok");
    }

    @ApiOperation("上传文件2")
    @PostMapping("/fileUpload2")
    public ResponseModel uploadFile2(@RequestPart MultipartFile file) {


        fileService.uploadFile(file);

        return new ResponseModel("200","ok");
    }
}
  • feign的对应的controller
 @ApiOperation("上传文件")
    @PostMapping("/fileUpload")
    public ResponseModel uploadFile(@RequestPart MultipartFile uploadfile) {


        fileService.uploadFile(uploadfile);

        return new ResponseModel("200","ok");
    }

运行结果

  • 调用fileUpload 接口 --》上传成功
  • 调用fileUpload2 接口 --》上传失败

远程端报错信息
在这里插入图片描述

解决

  • 问题原因 :前后端参数名对应不一致

可能原因:
前后端参数名对应不一致
spring.servlet.multipart.enabled=false即关闭文件上传支持
配置文件中指定了文件上传时的大小值问题
切换内嵌容器tomcat到undertow的配置问题
spring.servlet.multipart.location=/tmp指定了临时文件站,但路径不存在
多次读取HttpServletRequest流
springboot已经有CommonsMultipartResolver,需要排除原有的Multipart配置@EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
摘抄文章链接

  • 解决方案: 添加变量名,利用MultipartFile.getName
   @ApiOperation("上传文件2")
    @PostMapping("/fileUpload2")
    public ResponseModel uploadFile2(@RequestPart MultipartFile file) {


        try {
            file = new MultipartFileDto("uploadfile",file.getOriginalFilename(),file.getContentType(), file.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }

        fileService.uploadFile(file);

        return new ResponseModel("200","ok");
    }
 

import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
 * @program: atomic-upms
 * @description:
 * @author: zzg@xnj
 * @create: 2024-08-20 20:24
 **/

public class MultipartFileDto implements MultipartFile {
    private final String name;

    private String originalFilename;

    private String contentType;

    private final byte[] content;

    /**
     * Create a new MultipartFileDto with the given content.
     * @param name the name of the file
     * @param content the content of the file
     */
    public MultipartFileDto(String name, byte[] content) {
        this(name, "", null, content);
    }

    /**
     * Create a new MultipartFileDto with the given content.
     * @param name the name of the file
     * @param contentStream the content of the file as stream
     * @throws IOException if reading from the stream failed
     */
    public MultipartFileDto(String name, InputStream contentStream) throws IOException {
        this(name, "", null, FileCopyUtils.copyToByteArray(contentStream));
    }

    /**
     * Create a new MultipartFileDto with the given content.
     * @param name the name of the file
     * @param originalFilename the original filename (as on the client's machine)
     * @param contentType the content type (if known)
     * @param content the content of the file
     */
    public MultipartFileDto(String name, String originalFilename, String contentType, byte[] content) {
        this.name = name;
        this.originalFilename = (originalFilename != null ? originalFilename : "");
        this.contentType = contentType;
        this.content = (content != null ? content : new byte[0]);
    }

    /**
     * Create a new MultipartFileDto with the given content.
     * @param name the name of the file
     * @param originalFilename the original filename (as on the client's machine)
     * @param contentType the content type (if known)
     * @param contentStream the content of the file as stream
     * @throws IOException if reading from the stream failed
     */
    public MultipartFileDto(String name, String originalFilename, String contentType, InputStream contentStream)
            throws IOException {

        this(name, originalFilename, contentType, FileCopyUtils.copyToByteArray(contentStream));
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public String getOriginalFilename() {
        return this.originalFilename;
    }

    @Override
    public String getContentType() {
        return this.contentType;
    }

    @Override
    public boolean isEmpty() {
        return (this.content.length == 0);
    }

    @Override
    public long getSize() {
        return this.content.length;
    }

    @Override
    public byte[] getBytes() throws IOException {
        return this.content;
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return new ByteArrayInputStream(this.content);
    }

    @Override
    public void transferTo(File dest) throws IOException, IllegalStateException {
        FileCopyUtils.copy(this.content, dest);
    }

}

事后诸葛亮

  • feign调用

参数没有生效??在这里插入图片描述

在这里插入图片描述

  • 正常表单请求
    在这里插入图片描述
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值