`

springcloud feign上传文件

阅读更多

最近用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用这个代码

}

 

这里如此接收参数便可。

 

经测试是没有问题.

 

 

 

0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics