解决Feign无法传递HttpServletResponse
场景:前端调用的接口写在portal层,现在有一个下载的场景需要portal层通过feign调用Neams模块后端服务。
解决方法:使用feign原生的Response做返回,再将feign的Response转换成HttpServletResponse
服务提供方
/**
* 下载接口
*/
@ApiOperation(value = "基础档案下载")
@GetMapping(value = "/download/{beid}")
public void download(HttpServletResponse response,@PathVariable("beid") String beid) throws Exception {
try{
eamsBaseRecordService.download(response, beid);
}catch (Throwable e){
log.error(e.getMessage());
throw new RuntimeException(e);
}
}
调用方
FeignClient
@FeignClient(contextId = "NeamsRemoteClient",
name = "${nstc.service.neams.hosted-service:neams-service}",
path = "${nstc.service.neams.context-path:}",
fallback = RemoteFallback.class
)
public interface NeamsRemoteClient {
//不需要传 HttpServletResponse
@ApiOperation(value = "远程文件下载")
@GetMapping(value = "/neams/eamsbaserecord/download/{beid}")
Response download(@PathVariable("beid") String beid) throws Exception;
}
App下载附件Controller入口
@GetMapping("/download")
@ApiOperation(value = "App下载附件")
public void download(HttpServletResponse response, @ApiParam(value = "工单ID") @RequestParam String fileId){
serviceLocator.getG20AppService().downloadFile(response, fileId);
}
Service具体处理
@Override
public void downloadFile(HttpServletResponse response, String fileId) {
log.info("downloadFile fileId={}", fileId);
try {
//feign.Response
Response download = neamsRemoteClient.download(fileId);
log.info("downloadFile download={}", download.status()+";"+download.reason());
feignResp2ServletResp(download, response);
} catch (Exception e) {
log.error("downloadFile err:", e);
}
}
/**
* 解决Feign无法传递HttpServletResponse
* @param feignResponse
* @param response
* @throws IOException
*/
public static void feignResp2ServletResp(Response feignResponse, HttpServletResponse response) throws IOException {
Response.Body body = feignResponse.body();
try (InputStream inputStream = body.asInputStream(); OutputStream outputStream = response.getOutputStream()) {
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, feignResponse.headers().get(HttpHeaders.CONTENT_DISPOSITION).stream().findFirst().get());
response.setContentType(feignResponse.headers().get(HttpHeaders.CONTENT_TYPE).stream().findFirst().get());
IOUtils.copy(inputStream, outputStream);
}
}