SpringCloud是当下最流行的分布式服务解决方案之一,是微服务架构的集大成者,将一系列优秀的组件进行了整合。SpringCloud基于springboot构建,对于使用过SpringBoot的同学来说,上手比较容易。

今天学习一下 使用feign跨服务文件下载。
一. 服务提供者

public static void export(Class<? extends BaseRowModel> clazz,
                              List<? extends BaseRowModel> data,
                              String fileName,
                              String sheetName,
                              HttpServletResponse response) {
        try {
            response.reset();
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            response.setHeader("Connection", "close");
            response.setHeader("Content-type", "application/vnd.ms-excel;charset=utf-8");
            ExcelWriter writer = EasyExcelFactory.getWriter(response.getOutputStream());
            List<List<String>> head = new ArrayList<>();
            ExcelHeadProperty excelHeadProperty = new ExcelHeadProperty(clazz, head);

            Sheet sheet = new Sheet(1, 1, clazz);
            sheet.setHead(excelHeadProperty.getHead());
            sheet.setSheetName(sheetName);
            setSheetStyle(sheet);//一个设置excel风格的方法,可自己定义
            writer.write(data, sheet);
            writer.finish();
        } catch (IOException e) {
            log.error("下载" + fileName + "失败: " + e);
        }
    }
  • Controller下载接口
@GetMapping(value = "/export", produces = {"application/json"}, consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public void export(HttpServletResponse response) {
        ExcelUtil.export(AnObject.class, aDataList, "excel名称", "sheet名称", response);
    }

说明:AnObject需要继承BaseRowModel;Controller的返回必需是void,且不能被包裹一层例如ResponseDto;

二. 服务消费者

  • feign接口,当编写调用提供者的文件下载服务时,需要使用feign.Response作为返回参数,而不是HttpServeletResponse或和提供者一样的void
@FeignClient(name = "${feign.url.xx:someServiceName}", path = "/feign", fallbackFactory = FeignDownLoadApiFallback.class)
public interface FeignDownLoadApi {

    @GetMapping(value = "/export", produces = {"application/json"})
    Response export();
}
  • Controller下载接口,需要使用ResponseEntity<byte[]>做返回参数
@GetMapping(value = "/export", produces = {"application/json"})
    public ResponseEntity<byte[]> export() {
        ResponseEntity<byte[]> result = null;
        Response response = feignDownLoadApi.export(batchCode);
        Response.Body body = response.body();
        try (InputStream inputStream = body.asInputStream()) {
            // feign文件下载
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] buf = new byte[10240];
            while (true) {
                int len = inputStream.read(buf);
                if (len < 0) {
                    break;
                }
                bos.write(buf, 0, len);
            }
		   //网上也有这种将数据读入到byte[]里面的操作,但是会有问题,有可能一些数据没有读完整,导致最终下载的文件打不开,所以最好还是上面那种常规的读取操作
            //byte[] b = new byte[inputStream.available()];
      	    //inputStream.read(b);
            byte[] b = bos.toByteArray();
            HttpHeaders heads = new HttpHeaders();
            heads.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=123");
            heads.add(HttpHeaders.CONTENT_TYPE, "application/vnd.ms-excel;charset=utf-8");
            heads.add(HttpHeaders.CONNECTION, "close");

            result = new ResponseEntity<>(b, heads, HttpStatus.OK);
        } catch (IOException e) {
            
        }
        return result;
    }
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐