调用方
package com.foresealife.doc.management.remoting.impl;
import com.foresealife.doc.management.common.constant.Constant;
import com.foresealife.doc.management.common.enums.MsgInfoEnum;
import com.foresealife.doc.management.common.utils.CommonMultipartFile;
import com.foresealife.doc.management.remoting.FileObjectServiceApiService;
import com.foresealife.doc.management.remoting.FileRuleServiceApiService;
import com.foresealife.doc.management.web.dto.FileDownLoadObjectDTO;
import com.foresealife.doc.management.web.dto.FileRuleDTO;
import com.foresealife.doc.management.web.dto.FileUploadObjectDTO;
import com.foresealife.doc.management.web.vo.FileObjectVO;
import com.foresealife.doc.management.web.vo.FileRuleVO;
import com.foresealife.service.common.dto.ExecuteResult;
import com.foresealife.service.common.exception.ForesealifeServerException;
import feign.Response;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.InputStream;
import java.util.Objects;
/**
*
* @ClassName: FileObjectServiceImpl
* @Description:调文件上传及下载服务上传文件
* @author huangp005
* @date 2021-12-27
*
*/
@Service
@Slf4j
public class FileObjectServiceImpl {
@Resource
private FileObjectServiceApiService fileObjectServiceApiService;
@Resource
private FileRuleServiceApiService fileRuleServiceApiService;
private static final int NUM_5 = 5;
/**
*
* @Title: getFileStorePathAndUploadFile
* @Description: 调文件服务获取存储路径并调文件服务接口上传文件
* @param @param fileName
* @param @param documentNo
* @param @param fileContent
* @param @param businessType
* @param @return 参数
* @return FileObjectVO 返回类型
* @throws
*/
public FileObjectVO getFileStorePathAndUploadFile(String fileName, String documentNo, byte[] fileContent,
String businessType) throws InterruptedException {
//获取路径
final FileRuleVO fileRuleVO = getFileStorePath(documentNo, businessType);
//json转xml xml转multipartFile
MultipartFile multipartFile = new CommonMultipartFile(fileName, MediaType.APPLICATION_OCTET_STREAM.toString(),
fileContent);
//上传文件
return uploadFileToFileObject(multipartFile, fileRuleVO.getStorePath(), documentNo);
}
/**
*
* @Title: uploadFileToFileObject
* @Description: 根据存储路径调文件服务上传文件
* @param @param multipartFile
* @param @param storePath
* @param @param businessNo
* @param @return 参数
* @return FileObjectVO 返回类型
* @throws
*/
public FileObjectVO uploadFileToFileObject(MultipartFile multipartFile, String storePath, String businessNo) throws InterruptedException {
final FileUploadObjectDTO fileUploadObjectDTO = FileUploadObjectDTO.buildFileUploadObjectDto(businessNo,
storePath);
ExecuteResult<FileObjectVO> result = new ExecuteResult<>();
for (int i = 0; i < NUM_5; i++) {
try {
result = fileObjectServiceApiService.uploadFile(multipartFile,
fileUploadObjectDTO.getBusinessNo(), fileUploadObjectDTO.getStorePath(),
fileUploadObjectDTO.getRequestSource());
break;
} catch (Exception e) {
if(i >= 4){
throw e;
}
log.info("第"+(i+1)+"次调文件服务上传接口异常,业务号:{},{}",businessNo,e);
Thread.sleep(1000);
}
}
//请求异常
if (ObjectUtils.notEqual(Constant.SUCCESS_CODE, result.getSuccess())) {
throw new ForesealifeServerException(MsgInfoEnum.INVOKE_FILEOBJECT_SERVICE_UPLOAD_FILE_FAIL.getResultCode(),
MsgInfoEnum.INVOKE_FILEOBJECT_SERVICE_UPLOAD_FILE_FAIL.getResultMsg());
}
return result.getResult();
}
/**
*
* @Title: downLoadFileFromFileObject
* @Description: 根据文件路径ID调文件服务下载文件
* @param @param documentNo
* @param @param filePathId
* @param @return
* @param @throws IOException 参数
* @return InputStream 返回类型
* @throws
*/
@SneakyThrows
public InputStream downLoadFileFromFileObject(String bizNo, String filePathId){
FileDownLoadObjectDTO fileDownLoadObjectDTO = FileDownLoadObjectDTO.builder()
.businessNo(bizNo)
.filePathId(filePathId)
.requestSource(Constant.MSPDS)
.build();
Response response = null;
for (int i = 0; i < NUM_5; i++) {
try {
response = fileObjectServiceApiService.downloadFileByPathId(fileDownLoadObjectDTO);
break;
} catch (Exception e) {
if(i >= 4){
throw e;
}
log.info("第"+(i+1)+"次调文件服务下载接口异常,业务号:{},{}",bizNo,e);
Thread.sleep(1000);
}
}
//请求异常
if (Objects.isNull(response) || ObjectUtils.notEqual(Constant.RES_200, response.status())) {
throw new ForesealifeServerException(MsgInfoEnum.INVOKE_LOADFILE_FROM_FILEOBJECT_FAIL.getResultCode(),
MsgInfoEnum.INVOKE_LOADFILE_FROM_FILEOBJECT_FAIL.getResultMsg());
}
return response.body().asInputStream();
}
/**
* 根据文件路径下载文件
* @param bizNo
* @param filePath
* @return
*/
@SneakyThrows
public InputStream downLoadFileByFilePath(String bizNo, String filePath){
FileDownLoadObjectDTO fileDownLoadObjectDTO = FileDownLoadObjectDTO.builder()
.businessNo(bizNo)
.storePath(filePath)
.requestSource(Constant.MSPDS)
.build();
Response response = null;
for (int i = 0; i < NUM_5; i++) {
try {
response = fileObjectServiceApiService.downloadFileByFilePath(fileDownLoadObjectDTO);
break;
} catch (Exception e) {
if(i >= 4){
throw e;
}
log.info("第"+(i+1)+"次调文件服务下载接口异常,业务号:{},{}",bizNo,e);
Thread.sleep(1000);
}
}
//请求异常
if (Objects.isNull(response) || ObjectUtils.notEqual(Constant.RES_200, response.status())) {
throw new ForesealifeServerException(MsgInfoEnum.INVOKE_LOADFILE_FROM_FILEOBJECT_FAIL.getResultCode(),
MsgInfoEnum.INVOKE_LOADFILE_FROM_FILEOBJECT_FAIL.getResultMsg());
}
return response.body().asInputStream();
}
/**
*
* @Title: getFileStorePath
* @Description: 获取文件存储路径
* @param @param documentNo
* @param @param businessType
* @param @return 参数
* @return FileRuleVO 返回类型
* @throws
*/
public FileRuleVO getFileStorePath(String documentNo, String businessType) {
final FileRuleDTO fileRuleDTO = FileRuleDTO.buildFileRuleDtoByDocumentNo(documentNo, businessType);
ExecuteResult<FileRuleVO> result = fileRuleServiceApiService.getFileStorePath(fileRuleDTO);
//请求异常
if (ObjectUtils.notEqual(Constant.SUCCESS_CODE, result.getSuccess())) {
throw new ForesealifeServerException(
MsgInfoEnum.INVOKE_FILERULE_SERVICE_GET_FILESTOREPATH_FAIL.getResultCode(),
MsgInfoEnum.INVOKE_FILERULE_SERVICE_GET_FILESTOREPATH_FAIL.getResultMsg());
}
return result.getResult();
}
}
package com.foresealife.doc.management.remoting;
import com.foresealife.doc.management.config.FeignMultipartSupportConfig;
import com.foresealife.doc.management.web.dto.FileDownLoadObjectDTO;
import com.foresealife.doc.management.web.dto.FileRuleDTO;
import com.foresealife.doc.management.web.vo.FileObjectVO;
import com.foresealife.doc.management.web.vo.FileRuleVO;
import com.foresealife.service.common.dto.ExecuteResult;
import feign.Response;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
*
* @ClassName: FileObjectServiceApiService
* @Description: 调文件上传及下载服务接口
* @author huangp005
* @date 2021-12-27
*
*/
@FeignClient(value = "msp-fss-fileobject-service", primary = false, configuration = FeignMultipartSupportConfig.class)
@RefreshScope
public interface FileObjectServiceApiService {
/**
*
* @Title: uploadFile
* @Description: 上传文件
* @param @param multipartFile
* @param @param businessNo
* @param @param storePath
* @param @param requestSource
* @param @return 参数
* @return ExecuteResult<FileObjectVO> 返回类型
* @throws
*/
@PostMapping(value = "/fileobject/uploadFile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
ExecuteResult<FileObjectVO> uploadFile(@RequestPart("file") MultipartFile multipartFile,
@RequestParam("businessNo") String businessNo, @RequestParam("storePath") String storePath,
@RequestParam("requestSource") String requestSource);
/**
*
* @Title: downloadFileByPathId
* @Description: 获取json文件
* @param @param fileDownLoadObjectDTO
* @param @return 参数
* @return Response 返回类型
* @throws
*/
@PostMapping(value = "/fileobject/downloadFileByPathId", headers = { "msp-ds-document-service" })
Response downloadFileByPathId(@RequestBody FileDownLoadObjectDTO fileDownLoadObjectDTO);
@PostMapping(value = "/fileobject/downloadFile", headers = { "msp-ds-document-service" })
Response downloadFileByFilePath(@RequestBody FileDownLoadObjectDTO fileDownLoadObjectDTO);
/**
*
* @Title: getFileStorePath
* @Description: 获取文件路径
* @param @param fileRuleDTO
* @param @return 参数
* @return ExecuteResult<FileRuleVO> 返回类型
* @throws
*/
@PostMapping(value = "/filerule/getFileStorePath", headers = { "msp-ds-document-service" })
ExecuteResult<FileRuleVO> getFileStorePath(@RequestBody FileRuleDTO fileRuleDTO);
}
提供方
package com.foresealife.fileplatform.web.api;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson.JSONObject;
import com.foresealife.fileplatform.fileobject.dto.FileDownLoadObjectDTO;
import com.foresealife.fileplatform.fileobject.service.FileObjectService;
import com.foresealife.fileplatform.fileobject.vo.FileObjectReturnVO;
import com.foresealife.fileplatform.fileobject.vo.FileParamVO;
import com.foresealife.service.common.base.BaseController;
import com.foresealife.service.common.dto.ExecuteResult;
/**
* 文件上传及规则微服务接口
*
* @author huangp005
*
*/
@Controller
@ResponseBody
@RefreshScope
@RequestMapping(value = "/fileobject")
public class FileObjectController extends BaseController {
@Autowired
FileObjectService fileObjectService;
private static final Logger log = LoggerFactory.getLogger(FileObjectController.class);
/**
* 上传文件
*
* @param multipartFile
* @param params
* @return
*/
@PostMapping(value = "/uploadFile")
public ExecuteResult<FileObjectReturnVO> uploadFile(@Valid @RequestParam("file") MultipartFile multipartFile,
@NotNull FileParamVO params) {
log.info("上传文件,params:{}", params);
FileObjectReturnVO returnVo = fileObjectService.uploadFile(multipartFile, params);
ExecuteResult<FileObjectReturnVO> ets = new ExecuteResult<>();
ets.setResult(returnVo);
return ets;
}
/**
* 下载文件
*
* @param params
* @return
*/
@PostMapping(value = "/downloadFile")
public ResponseEntity<InputStreamResource> downloadFile(@RequestBody @Valid FileParamVO params) {
log.info("下载文件,params:{}", params);
return fileObjectService.downloadFile(params);
}
/**
* 下载文件
*
* @param params
* @return
*/
@PostMapping(value = "/downloadFileByPathId")
public ResponseEntity<InputStreamResource> downloadFileByPathId(
@RequestBody @Valid FileDownLoadObjectDTO fileDownLoadObjectDTO) {
log.info("根据ID下载文件,params:{}", fileDownLoadObjectDTO);
return fileObjectService.downloadFileByPathId(fileDownLoadObjectDTO);
}
}
package com.foresealife.fileplatform.fileobject.service.impl;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Objects;
import javax.annotation.Resource;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.foresealife.fileplatform.common.Constant;
import com.foresealife.fileplatform.common.enums.FileErrorEnum;
import com.foresealife.fileplatform.common.enums.RequestSource;
import com.foresealife.fileplatform.fileobject.dto.FileBusinessLogDTO;
import com.foresealife.fileplatform.fileobject.dto.FileDownLoadObjectDTO;
import com.foresealife.fileplatform.fileobject.entity.FileBusinessLog;
import com.foresealife.fileplatform.fileobject.mapper.FileBusinessLogDao;
import com.foresealife.fileplatform.fileobject.service.FileObjectService;
import com.foresealife.fileplatform.fileobject.vo.FileObjectReturnVO;
import com.foresealife.fileplatform.fileobject.vo.FileParamVO;
import com.foresealife.service.common.exception.ForesealifeServerException;
/**
* 文件路径获取及规则服务实现类
*
* @author:huangp005
*/
@Service
public class FileObjectServiceImpl implements FileObjectService {
private static final Logger log = LoggerFactory.getLogger(FileObjectServiceImpl.class);
@Resource
private FileBusinessLogDao fileBusinessLogDao;
@Override
public FileObjectReturnVO uploadFile(MultipartFile multipartFile, FileParamVO params) {
String businessNo = params.getBusinessNo();
log.info("businessNo:{}上传文件开始", businessNo);
FileObjectReturnVO returnVO = new FileObjectReturnVO();
FileBusinessLog logEntity = new FileBusinessLog();
long startTime = System.currentTimeMillis();
FileBusinessLogDTO logDto = new FileBusinessLogDTO();
String fileName = multipartFile.getOriginalFilename();
//初始化logEntity
BeanUtils.copyProperties(logDto, logEntity);// 传入默认值
BeanUtils.copyProperties(params, logEntity);
logEntity.setCallType(Constant.CALL_TYPE_2);
log.info("businessNo:{},上传文件,初始化logEntity对象,{}",businessNo, logEntity);
File newFile = new File(params.getStorePath());
try (FileOutputStream os = new FileOutputStream(newFile + File.separator + fileName)) {
BeanUtils.copyProperties(params, returnVO);
FileCopyUtils.copy(multipartFile.getInputStream(), os);
returnVO.setStorePath(params.getStorePath() + File.separator + fileName);
logEntity.setStatus(Constant.SUCCESS);
logEntity.setReturnXml(returnVO.toString());
} catch (IOException e) {
log.error(businessNo + "上传文件异常",e);
logEntity.setStatus(Constant.FAIL);
logEntity.setReturnXml(e.getMessage());
fileBusinessLogDao.insert(logEntity);
}
String storePath = params.getStorePath() + File.separator + fileName;
logEntity.setStorePath(storePath);
Long sumRunTime = System.currentTimeMillis() - startTime;
logEntity.setRequestTime(sumRunTime.toString());
fileBusinessLogDao.insert(logEntity);
returnVO.setFilePathId(String.valueOf(logEntity.getLogId()));
log.info("businessNo:{},上传文件保存路径:StorePath:{},FilePathId:{}",businessNo, storePath,logEntity.getLogId());
log.info("businessNo:{}上传文件结束 总耗时:{}ms", businessNo,sumRunTime);
if (Constant.FAIL.equals(logEntity.getStatus())) {
throw new ForesealifeServerException(FileErrorEnum.EXPRESSION_UPLOAD_FILE_ERROR.getKey(),
FileErrorEnum.EXPRESSION_UPLOAD_FILE_ERROR.getValue() + logEntity.getReturnXml());
}
return returnVO;
}
@Override
public ResponseEntity<InputStreamResource> downloadFile(FileParamVO params) {
String businessNo = params.getBusinessNo();
log.info("businessNo:{}下载文件开始", businessNo);
long startTime = System.currentTimeMillis();
ResponseEntity<InputStreamResource> entity = null;
FileBusinessLog logEntity = new FileBusinessLog();
FileBusinessLogDTO logDto = new FileBusinessLogDTO();
//初始化logEntity对象
BeanUtils.copyProperties(logDto, logEntity);// 传入默认值
BeanUtils.copyProperties(params, logEntity);
logEntity.setCallType(Constant.CALL_TYPE_3);
log.info("businessNo:{},下载文件,初始化logEntity对象,{}",businessNo, logEntity);
FileSystemResource file = new FileSystemResource(params.getStorePath());
if (!file.exists()) {
log.error("businessNo:{}下载文件异常,文件不存在:{}",businessNo,file.getPath());
logEntity.setStatus(Constant.FAIL);
// 文件不存在
throw new ForesealifeServerException(FileErrorEnum.EXPRESSION_FILE_NOT_FOND_ERROR.getKey(),
FileErrorEnum.EXPRESSION_FILE_NOT_FOND_ERROR.getValue());
}
try {
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getFilename()));
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
entity = ResponseEntity.ok().headers(headers).contentLength(file.contentLength())
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(new InputStreamResource((file.getInputStream())));
logEntity.setStatus(Constant.SUCCESS);
}catch (IOException e) {
log.error(businessNo + "下载文件异常",e);
logEntity.setStatus(Constant.FAIL);
logEntity.setRequestTime(String.valueOf(System.currentTimeMillis() - startTime));
fileBusinessLogDao.insert(logEntity);
}
Long sumRunTime = System.currentTimeMillis() - startTime;
logEntity.setRequestTime(sumRunTime.toString());
fileBusinessLogDao.insert(logEntity);
log.info("businessNo:{}下载文件结束 总耗时:{}ms", businessNo,sumRunTime);
if (Constant.FAIL.equals(logEntity.getStatus())) {
throw new ForesealifeServerException(FileErrorEnum.EXPRESSION_UPLOAD_FILE_ERROR.getKey(),
FileErrorEnum.EXPRESSION_UPLOAD_FILE_ERROR.getValue() + logEntity.getReturnXml());
}
return entity;
}
@Override
public ResponseEntity<InputStreamResource> downloadFileByPathId(FileDownLoadObjectDTO fileDownLoadObjectDTO) {
FileParamVO params = buildFileParamVo(fileDownLoadObjectDTO);
//下载文件
return downloadFile(params);
}
private FileParamVO buildFileParamVo(FileDownLoadObjectDTO fileDownLoadObjectDTO) {
FileParamVO fileParamVO = new FileParamVO();
BeanUtils.copyProperties(fileDownLoadObjectDTO, fileParamVO);
FileBusinessLog fileBusinessLog = fileBusinessLogDao
.selectByPrimaryKey(Integer.valueOf(fileDownLoadObjectDTO.getFilePathId()));
//找不到路径-抛异常
if (Objects.isNull(fileBusinessLog) || StringUtils.isBlank(fileBusinessLog.getStorePath())) {
throw new ForesealifeServerException(RequestSource.FILE_NOT_EXISTS);
}
fileParamVO.setStorePath(fileBusinessLog.getStorePath());
return fileParamVO;
}
}