spring cloud feign實現遠端呼叫服務傳輸檔案

藍之魚發表於2019-01-19

實踐案例包括兩個專案,服務提供者專案名:upload-service,呼叫服務專案名:upload-client,主要給出兩個服務之間的呼叫過程,檔案上傳功能不提供

專案框架:spring-boot 2.0.1.RELEASE、spring-cloud Finchley.RELEASE

依賴:

        <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>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>

一.檔案上傳服務upload-service
1.控制層

@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/ftp")
@Api(description = "檔案上傳控制")
public class FtpFileController {

    @Autowired
    private FtpFileService ftpFileService;

    /**
     * FTP檔案上傳
     *
     * @return
     */
    @PostMapping(value = "/uploadFile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public FtpApiResponse<FtpUploadResDTO> uploadFileFTP(@RequestPart(value = "file") MultipartFile file,
                                                         @RequestParam("logId") String logId) {
        FtpApiResponse<FtpUploadResDTO> result = new FtpApiResponse<>();
        LogUtil.updateLogId(logId);
        try {
            log.info("檔案上傳開始!}");
            Long startTime = System.currentTimeMillis();
            FtpUploadResDTO resDTO = ftpFileService.uploadFile(file);
            result.setData(resDTO);
            result.setSuccess(true);
            result.setTimeInMillis(System.currentTimeMillis() - startTime);
            log.info("檔案上傳結束 resDTO:{},耗時:{}", resDTO, (System.currentTimeMillis() - startTime));
        } catch (ServiceException e){
            result.setSuccess(false);
            result.setErrorCode(ErrorMsgEnum.FILE_UPLOAD_EXCEPTION.getCode());
            result.setErrorMsg(ErrorMsgEnum.FILE_UPLOAD_EXCEPTION.getMsg());
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorMsgEnum.SYSTEM_ERROR.getCode());
            result.setErrorMsg(ErrorMsgEnum.SYSTEM_ERROR.getMsg());
            log.info("檔案上傳失敗 Exception:{}", Throwables.getStackTraceAsString(e));
        }
        return result;
    }
}

2.業務層

@Service
@Slf4j
public class FtpFileService {

    @Autowired
    private FtpFileManager ftpFileManager;

    /**
     * 上傳檔案
     *
     * @param file
     * @return
     */
    public FtpUploadResDTO uploadFile(MultipartFile file) {
        try {
            //判斷上傳檔案是否為空
            if (null == file || file.isEmpty() || file.getSize() == 0) {
                log.info("傳入的檔案為空,file:{}", file);
                throw new ServiceException(ErrorMsgEnum.EMPTY_FILE);
            }
            //檔案上傳至ftp服務目錄
            FtpFileRecordDO ftpFileRecordDO = ftpFileManager.fileUploadToFtp(file);
            if (null == ftpFileRecordDO) {
                log.info("檔案上傳至ftp服務目錄異常");
                throw new ServiceException(ErrorMsgEnum.FILE_UPLOAD_TO_FTP_EXCEPTION);
            }
            return ftpFileManager.addFileRecord(ftpFileRecordDO);
        } catch (Exception e) {
            log.error("業務異常,case", e);
            throw new ServiceException(ErrorMsgEnum.SYSTEM_ERROR);
        }
    }
}

3.服務寫好後,需要把遠端介面暴露出去

@FeignClient(value  = "upload-service", configuration = UpDownFtpFacade.MultipartSupportConfig.class)
public interface UpDownFtpFacade {

    /**
     * FTP上傳檔案
     *
     * @param file 檔案
     * @param logId 日誌id
     * @return
     */
    @PostMapping(value = "/ftp/uploadFile",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    FtpApiResponse<FtpUploadResDTO> uploadFileFTP(@RequestPart(value = "file") MultipartFile file,
                                                  @RequestParam("logId") String logId);

    /**
     * 引用配置類MultipartSupportConfig.並且例項化
     */
    @Configuration
    class MultipartSupportConfig {
        @Bean
        public Encoder feignFormEncoder() {
            return new SpringFormEncoder();
        }
    }

}

二.檔案上傳客戶端upload-client

@Slf4j
@Component
public class FileManager {
     @Autowired
     private UpDownFtpFacade upDownFtpFacade;
     
     /**
     * 呼叫遠端上傳檔案介面
     *
     * @param file 待上傳的檔案
     * @return 下載路徑
     **/
    public FtpApiResponse<FtpUploadResDTO> requestFtpFacade(MultipartFile file) {
        try {
            DiskFileItem fileItem = (DiskFileItem) new DiskFileItemFactory().createItem("file",
                    MediaType.ALL_VALUE, true, file.getOriginalFilename());
            InputStream input = file.getInputStream();
            OutputStream os = fileItem.getOutputStream();
            IOUtils.copy(input, os);
            MultipartFile multi = new CommonsMultipartFile(fileItem);
            FtpApiResponse<FtpUploadResDTO> response = upDownFtpFacade.uploadFileFTP(multi, LogUtil.getLogId());
            if (null == response || !response.getSuccess() || null == response.getData()) {
                throw new ManagerException(ErrorMsgEnum.FIlE_UPLOAD_FAILED);
            }
            return response;
        } catch (Exception e) {
            throw new ManagerException(ErrorMsgEnum.FIlE_UPLOAD_FAILED);
        }
     }
}

相關文章