目录
文件上传、下载也是实际项目中会遇到的场景,本篇我们介绍下SpringCloud中如何使用Feign进行文件上传与下载
一、 Feign文件上传服务提供者
1. pom.xml 依赖jar
<!-- 引入文件feign文件上传依赖 -->
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form-spring</artifactId>
<version>3.0.3</version>
</dependency>
2. Feign 文件上传配置文件
@Configuration
public class FeignMultipartSupportConfig {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Bean
@Primary
@Scope("prototype")
public Encoder feignEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
@Bean
public feign.Logger.Level multipartLoggerLevel() {
return feign.Logger.Level.FULL;
}
}
3. FileUploadFeign中Api提供
@FeignClient(
contextId = "FileUploadFeign",
name = "user-service",
configuration = FeignMultipartSupportConfig.class
)
public interface FileUploadFeign {
/**
* 单个文件上传
* @RequestPart:文件传输
* @param file 文件
* @param type 目录
* @date: 2021/3/26 9:27
* @return: com.zlp.dto.UploadResp
*/
@PostMapping(value = "/uploadFile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
UploadResp uploadFile(@RequestPart(value = "file") MultipartFile file,
@RequestParam(value = "type") String type);
/**
* 多个文件上传
* @RequestPart:文件传输
* @param files 文件
* @param type 目录
* @date: 2021/3/26 9:27
* @return: com.zlp.dto.UploadResp
*/
@PostMapping(value = "/uploadFiles", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
List<UploadResp> uploadFiles(@RequestPart(value = "files") MultipartFile[] files, @RequestParam(value = "type") String type);
}
4. FileUploadFeignImpl中Api实现类
@RestController
@Slf4j(topic = "FileUploadFeignImpl")
@Api(value = "UserFeign", tags = "用户Feign")
public class FileUploadFeignImpl implements FileUploadFeign {
@Resource
private OssTemplate ossTemplate;
//目前所有文件都存放在该命名空间下
private final static String BucketName = "greenvalley";
@Override
public UploadResp uploadFile(MultipartFile file, String type) {
log.info("uploadFile.req type={}",type);
UploadResp uploadResp = new UploadResp();
String originalFilename = file.getOriginalFilename();
uploadResp.setFileName(originalFilename);
String filePath = IdUtil.simpleUUID() + StrUtil.DOT + FileUtil.extName(originalFilename);
if (!StringUtils.isEmpty(type)) {
filePath = type + StrUtil.SLASH + filePath;
}
try {
ossTemplate.putObject(BucketName, filePath, file.getInputStream());
String fileUrl = ConstantsUtil.HTTP_PREFIX + BucketName + StrUtil.DOT + ConstantsUtil.DOMAIN + StrUtil.SLASH + filePath;
uploadResp.setFileUrl(fileUrl);
return uploadResp;
} catch (Exception e) {
log.error("上传失败", e);
}
return null;
}
@Override
public List<UploadResp> uploadFiles(MultipartFile[] files, String type) {
List<UploadResp> uploadRespList = new ArrayList<>();
for (MultipartFile file : files) {
uploadRespList.add(this.uploadFile(file,type));
}
return uploadRespList;
}
}
二、 Feign文件下载服务提供者
1. FileDownFeign中Api提供
@FeignClient(
contextId = "fileDownFeign",
name = "file-web"
)
public interface FileDownFeign {
@PostMapping(value = "/v1/getObject",consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
ResponseEntity<byte[]> getObject(String downFileUrl);
@GetMapping("/downloadFile")
ResponseEntity<byte[]> downloadFile(@RequestParam(value = "fileType") String fileType) ;
}
2. FileDownFeignImpl中Api实现类
@RestController
@Slf4j(topic = "FileDownFeignImpl")
@Api(value = "FileDownFeign", tags = "文件下载模块")
public class FileDownFeignImpl implements FileDownFeign {
@Resource
private OssTemplate ossTemplate;
@Override
@PostMapping(value = "/v1/getObject")
public ResponseEntity<byte[]> getObject(String downFileUrl) {
downFileUrl = "test/2ca1024b993a41eab9b88de67fc8c294.mp4";
OSSObject ossObject = ossTemplate.getObject(downFileUrl);
HttpHeaders headers = new HttpHeaders();
ResponseEntity<byte[]> entity = null;
BufferedInputStream bis;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[10240];
try {
bis = new BufferedInputStream(ossObject.getObjectContent());
while (true) {
int len = bis.read(buf);
if (len < 0) {
break;
}
bos.write(buf, 0, len);
}
//将输出流转为字节数组,通过ResponseEntity<byte[]>返回
byte[] b = bos.toByteArray();
log.info("接收到的文件大小为:" + b.length);
HttpStatus status = HttpStatus.OK;
String imageName = "0001.mp4";
headers.setContentType(MediaType.ALL.APPLICATION_OCTET_STREAM);
headers.add("Content-Disposition", "attachment;filename=" + imageName);
entity = new ResponseEntity<>(b, headers, status);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return entity;
}
/**
* 文件(二进制数据)下载
*
* @param fileType 文件类型
* @return
*/
@GetMapping("/downloadFile")
public ResponseEntity<byte[]> downloadFile(String fileType) {
log.info("参数fileType: " + fileType);
HttpHeaders headers = new HttpHeaders();
ResponseEntity<byte[]> entity = null;
InputStream in = null;
try {
in = new FileInputStream(new File("C:\\Users\\user.DESKTOP-8A9L631\\Desktop\\遂人\\图片\\0001.png"));
int available = in.available();
log.info("文件大小={}", available);
byte[] bytes = new byte[available];
String imageName = "001.png";
imageName = new String(imageName.getBytes(), "iso-8859-1");
in.read(bytes);
headers.setContentType(MediaType.ALL.APPLICATION_OCTET_STREAM);
headers.add("Content-Disposition", "attachment;filename=" + imageName);
entity = new ResponseEntity<>(bytes, headers, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return entity;
}
}
三、 消费者调用
1.OrderController 控制层
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("order")
public class OrderController {
private final OrderService orderService;
/**
* 上传功能
* @param file MultipartFile
* @date: 2021/4/14 10:21
* @return: UploadResp
*/
@PostMapping("uploadFile")
public UploadResp uploadFile(@RequestParam("file") MultipartFile file) {
return orderService.uploadFile(file);
}
/**
* 下载功能
* @param response
* @param fileUrl
* @date: 2021/4/14 10:21
* @return: void
*/
@GetMapping("getObject")
public void getObject(HttpServletResponse response, String fileUrl) {
orderService.getObject(response, fileUrl);
}
}
2. OrderServiceImpl 消费者服务调用
@Service
@AllArgsConstructor
@Slf4j(topic = "OrderServiceImpl")
public class OrderServiceImpl implements OrderService {
private final FileDownFeign fileDownFeign;
private final FileUploadFeign fileUploadFeign;
@Override
public void getObject(HttpServletResponse response, String fileUrl) {
ResponseEntity<byte[]> responseEntity = fileDownFeign.downloadFile(fileUrl);
BufferedInputStream bis = null;
if (Objects.nonNull(responseEntity)) {
byte[] body = responseEntity.getBody();
if (Objects.nonNull(body)) {
try {
log.info("文件大小==>:{}", body.length);
String filename = "20210113001.jpg";
response.setContentType("application/octet-stream");
response.setHeader("Content-disposition", "attachment; filename=" + new String(filename.getBytes("utf-8"), "ISO8859-1"));
InputStream is = new ByteArrayInputStream(body);
bis = new BufferedInputStream(is);
OutputStream os = response.getOutputStream();
byte[] buffer = new byte[2048];
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
@Override
public UploadResp uploadFile(MultipartFile file) {
log.info("uploadFile==>");
String type = "suirenow";
UploadResp uploadResp = fileUploadFeign.uploadFile(file, type);
if (Objects.nonNull(uploadResp)) {
log.info("fileUploadFeign.uploadFile.resp uploadResp={}", JSON.toJSONString(uploadResp));
}
return uploadResp;
}
}