diff --git a/pmapi/src/test/java/com/ningdatech/pmapi/file/CommonInputStreamResource.java b/pmapi/src/main/java/com/ningdatech/pmapi/common/util/CommonInputStreamResource.java similarity index 97% rename from pmapi/src/test/java/com/ningdatech/pmapi/file/CommonInputStreamResource.java rename to pmapi/src/main/java/com/ningdatech/pmapi/common/util/CommonInputStreamResource.java index a0275e8..81e9cd3 100644 --- a/pmapi/src/test/java/com/ningdatech/pmapi/file/CommonInputStreamResource.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/common/util/CommonInputStreamResource.java @@ -1,4 +1,4 @@ -package com.ningdatech.pmapi.file; +package com.ningdatech.pmapi.common.util; import org.springframework.core.io.InputStreamResource; diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/gov/manage/GovProjectCollectionManage.java b/pmapi/src/main/java/com/ningdatech/pmapi/gov/manage/GovProjectCollectionManage.java index 404d64f..df0f4a0 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/gov/manage/GovProjectCollectionManage.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/gov/manage/GovProjectCollectionManage.java @@ -4,6 +4,8 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.collection.CollUtil; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -23,10 +25,12 @@ import com.ningdatech.pmapi.gov.model.vo.*; import com.ningdatech.pmapi.gov.service.*; import com.ningdatech.pmapi.projectdeclared.utils.GenerateProjectCodeUtil; import com.ningdatech.pmapi.projectlib.model.req.ProjectListReq; +import com.ningdatech.pmapi.provincial.manage.ProvincialManage; import com.ningdatech.pmapi.sys.model.entity.Role; import com.ningdatech.pmapi.user.entity.enumeration.RoleEnum; import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails; import com.ningdatech.pmapi.user.util.LoginUserUtil; +import com.ningdatech.pmapi.wps.manage.WpsConvertManage; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -39,11 +43,9 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.client.RestTemplate; +import java.lang.reflect.Field; import java.time.LocalDateTime; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.stream.Collectors; /** @@ -76,6 +78,8 @@ public class GovProjectCollectionManage { private final RestTemplate restTemplate; + private final WpsConvertManage wpsConvertManage; + @Value("${project.push-url}") private String pushUrl; @@ -425,7 +429,9 @@ public class GovProjectCollectionManage { saveApply.setBizTime(LocalDateTime.now()); saveApply.setUpdateBy(user.getUsername()); saveApply.setUpdateOn(LocalDateTime.now()); - projectApplyService.saveOrUpdate(saveApply); + if(projectApplyService.saveOrUpdate(saveApply)){ + uploadFileToProvincialOss(apply,oldApply,saveApply); + } } // 3.保存 审批信息 @@ -657,6 +663,8 @@ public class GovProjectCollectionManage { //改正逻辑删除 baseinfo.setDeleted(Boolean.TRUE); + baseinfo.setUpdateBy(username); + baseinfo.setUpdateOn(LocalDateTime.now()); baseinfoService.updateById(baseinfo); projectApplyService.update(Wrappers.lambdaUpdate(GovBizProjectApply.class) .eq(GovBizProjectApply::getBaseProjId,projId) @@ -779,4 +787,55 @@ public class GovProjectCollectionManage { log.info("推送删除失败,{}", e.getMessage()); } } + + /** + * 上传项目归集申报的文件到OSS 前提还要先转为PDF + * @param apply + * @param oldApply + */ + private void uploadFileToProvincialOss(GovBizProjectApplyDTO apply, + GovBizProjectApply oldApply,GovBizProjectApply saveApply) { + if(checkFieldHas(apply.getBaseProjBasisFile(),oldApply,"baseProjBasisFile")){ + JSONArray fileArray = JSON.parseArray(apply.getBaseProjBasisFile()); + StringJoiner sj = new StringJoiner(";"); + fileArray.forEach(j -> { + JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(j)); + byte[] btyes = wpsConvertManage.downloadToPdfStream(jsonObject.getLong("id")); + String oss = ProvincialManage.uploadToOss(btyes, jsonObject.getString("originalFileName")); + sj.add(oss); + }); + saveApply.setBaseProjBasisFilePdf(sj.toString()); + } + projectApplyService.updateById(saveApply); + } + + private Boolean checkFieldHas(String field,GovBizProjectApply oldApply,String fieldName){ + if(StringUtils.isBlank(field)){ + return Boolean.FALSE; + } + + //如果没有老值 + if(Objects.isNull(oldApply)){ + return Boolean.TRUE; + } + + //和老值做个对比 不一样则true + Class clazz = oldApply.getClass(); + String oldFiled = StringUtils.EMPTY; + try { + Field fieldDeclared = clazz.getDeclaredField(fieldName); + fieldDeclared.setAccessible(Boolean.TRUE); + oldFiled = Objects.nonNull(fieldDeclared.get(oldApply)) ? String.valueOf(fieldDeclared.get(oldApply)) : null; + } catch (NoSuchFieldException e) { + log.error("转换PDF文件出错" + e); + } catch (IllegalAccessException e) { + log.error("转换PDF文件出错" + e); + } + + if(!oldFiled.equals(field)){ + return Boolean.TRUE; + } + + return Boolean.FALSE; + } } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/gov/model/entity/GovBizProjectApply.java b/pmapi/src/main/java/com/ningdatech/pmapi/gov/model/entity/GovBizProjectApply.java index db6c5d9..b5ec5d6 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/gov/model/entity/GovBizProjectApply.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/gov/model/entity/GovBizProjectApply.java @@ -149,4 +149,7 @@ public class GovBizProjectApply implements Serializable { @ApiModelProperty("最后修改人") private String updateBy; + + @ApiModelProperty("立项依据材料PDF版") + private String baseProjBasisFilePdf; } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/provincial/contants/ProvincialContant.java b/pmapi/src/main/java/com/ningdatech/pmapi/provincial/contants/ProvincialContant.java new file mode 100644 index 0000000..88efe8b --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/provincial/contants/ProvincialContant.java @@ -0,0 +1,15 @@ +package com.ningdatech.pmapi.provincial.contants; + +/** + * @Classname ProvincialContant + * @Description + * @Date 2023/9/6 9:16 + * @Author PoffyZhang + */ +public interface ProvincialContant { + + class OssUpload { + public static final String OSS_UPLOAD_URL = "https://pms.zj.gov.cn/prometheus-zhejiang_file_service/api/v1/file/uploadFile"; + public static final String MEDIA_TYPE = "multipart/form-data"; + } +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/provincial/manage/ProvincialManage.java b/pmapi/src/main/java/com/ningdatech/pmapi/provincial/manage/ProvincialManage.java new file mode 100644 index 0000000..6e0967d --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/provincial/manage/ProvincialManage.java @@ -0,0 +1,56 @@ +package com.ningdatech.pmapi.provincial.manage; + +import com.alibaba.fastjson.JSON; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.pmapi.common.util.CommonInputStreamResource; +import com.ningdatech.pmapi.provincial.contants.ProvincialContant; +import com.ningdatech.pmapi.provincial.model.res.OssApiData; +import com.ningdatech.pmapi.provincial.model.res.OssApiResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.*; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; +import java.io.ByteArrayInputStream; +import java.util.Objects; + +/** + * @Classname ProvincialManage + * @Description + * @Date 2023/9/6 9:08 + * @Author PoffyZhang + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class ProvincialManage { + + public static String uploadToOss(byte[] fileBytes,String fileName) { + String url = ProvincialContant.OssUpload.OSS_UPLOAD_URL; + MultiValueMap params = new LinkedMultiValueMap<>(); + ByteArrayInputStream inputStream = new ByteArrayInputStream(fileBytes); + CommonInputStreamResource commonInputStreamResource = new CommonInputStreamResource(inputStream, fileBytes.length, fileName); + params.add("file", commonInputStreamResource); + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + MediaType type = MediaType.parseMediaType(ProvincialContant.OssUpload.MEDIA_TYPE); + headers.setContentType(type); + HttpEntity formEntity = new HttpEntity(params, headers); + ResponseEntity res = restTemplate.postForEntity(url, formEntity, OssApiResponse.class); + log.info("oss res :{}", res); + OssApiResponse body = res.getBody(); + if(Objects.isNull(body)){ + throw new BizException("上传省局oss请求失败"); + } + + if(HttpStatus.OK.value() != body.getRespCode()){ + throw new BizException("上传省局oss失败:" + body.getRespMsg()); + } + + OssApiData ossApiData = JSON.parseObject(JSON.toJSONString(body.getData()), OssApiData.class); + + return ossApiData.getAccessUrl(); + } +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/provincial/model/res/OssApiData.java b/pmapi/src/main/java/com/ningdatech/pmapi/provincial/model/res/OssApiData.java new file mode 100644 index 0000000..0e1fff7 --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/provincial/model/res/OssApiData.java @@ -0,0 +1,33 @@ +package com.ningdatech.pmapi.provincial.model.res; + +import com.ningdatech.basic.enumeration.Status; +import com.ningdatech.basic.model.ApiStatus; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *

+ * OssApiResponse - + *

+ * + * @author ZPF + * @since 14:29 2022/9/29 + */ +@Data +@NoArgsConstructor +public class OssApiData implements Serializable { + + private String fileId; + + private String fileName; + + private String accessUrl; + + private Long fileSize; + + private String uploadUserCode; + + private String ossObject; +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/provincial/model/res/OssApiResponse.java b/pmapi/src/main/java/com/ningdatech/pmapi/provincial/model/res/OssApiResponse.java new file mode 100644 index 0000000..0507d73 --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/provincial/model/res/OssApiResponse.java @@ -0,0 +1,120 @@ +package com.ningdatech.pmapi.provincial.model.res; + +import com.ningdatech.basic.enumeration.Status; +import com.ningdatech.basic.model.ApiStatus; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *

+ * OssApiResponse - + *

+ * + * @author ZPF + * @since 14:29 2022/9/29 + */ +@Data +@NoArgsConstructor +public class OssApiResponse implements Serializable { + private static final long serialVersionUID = 1L; + + public static final int SUCCESS_CODE = 200; + + public static final String SUCCESS_MSG = "成功"; + + public static final int ERROR_CODE = 500; + + public static final String ERROR_MSG = "Internal server error"; + + /** + * 状态码 + */ + private Integer respCode; + + /** + * 返回描述 + */ + private String respMsg; + + /** + * 返回数据 + */ + private T data; + + /** + * 全参构造函数 + * + * @param respCode 状态码 + * @param respMsg 返回内容 + * @param data 返回数据 + */ + private OssApiResponse(Integer respCode, String respMsg, T data) { + this.respCode = respCode; + this.respMsg = respMsg; + this.data = data; + } + + /** + * 构造一个自定义的API返回 + * + * @param respCode 状态码 + * @param respMsg 返回内容 + * @param data 返回数据 + * @return ApiResponse + */ + public static OssApiResponse of(Integer respCode, String respMsg, T data) { + return new OssApiResponse(respCode, respMsg, data); + } + + /** + * 构造一个成功且不带数据的API返回 + * + * @return ApiResponse + */ + public static OssApiResponse ofSuccess() { + return ofSuccess(null); + } + + /** + * 构造一个成功且带数据的API返回 + * + * @param data 返回数据 + * @return ApiResponse + */ + public static OssApiResponse ofSuccess(T data) { + return ofStatus(Status.OK, data); + } + + /** + * 构造一个成功且自定义消息的API返回 + * + * @param msg 返回内容 + * @return ApiResponse + */ + public static OssApiResponse ofMessage(String msg) { + return of(Status.OK.getCode(), msg, null); + } + + /** + * 构造一个有状态的API返回 + * + * @param status 状态 {@link Status} + * @return ApiResponse + */ + public static OssApiResponse ofStatus(ApiStatus status) { + return ofStatus(status, null); + } + + /** + * 构造一个有状态且带数据的API返回 + * + * @param status 状态 {@link Status} + * @param data 返回数据 + * @return ApiResponse + */ + public static OssApiResponse ofStatus(ApiStatus status, T data) { + return of(status.getCode(), status.getReasonPhrase(), data); + } +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/provincial/utils/FileUtil.java b/pmapi/src/main/java/com/ningdatech/pmapi/provincial/utils/FileUtil.java new file mode 100644 index 0000000..2cdc99b --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/provincial/utils/FileUtil.java @@ -0,0 +1,32 @@ +package com.ningdatech.pmapi.provincial.utils; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; + +/** + * @Classname FileUtil + * @Description + * @Date 2023/9/6 9:09 + * @Author PoffyZhang + */ +public class FileUtil { + public static byte[] getBytesByFile(File file) { + try { + FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream bos = new ByteArrayOutputStream(1000); + byte[] b = new byte[1000]; + int n; + while ((n = fis.read(b)) != -1) { + bos.write(b, 0, n); + } + fis.close(); + byte[] data = bos.toByteArray(); + bos.close(); + return data; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/wps/manage/WpsConvertManage.java b/pmapi/src/main/java/com/ningdatech/pmapi/wps/manage/WpsConvertManage.java index 42b7401..ce99659 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/wps/manage/WpsConvertManage.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/wps/manage/WpsConvertManage.java @@ -96,6 +96,11 @@ public class WpsConvertManage { downloadAndToPdf(file, response); } + public byte[] downloadToPdfStream(Long fileId) { + com.ningdatech.file.entity.File file = fileService.getById(fileId); + return downloadAndToPdf(file); + } + private void downloadAndToPdf(com.ningdatech.file.entity.File file, HttpServletResponse response) { OSS oss = new OSSClientBuilder().build(fileServerProperties.getAli().getEndpoint(), fileServerProperties.getAli().getAccessKeyId(), fileServerProperties.getAli().getAccessKeySecret()); AtomAgent ha = new AtomAgent(WpsContant.WPS_CONVERT_URL_ONLINE); @@ -154,6 +159,57 @@ public class WpsConvertManage { } } + private byte[] downloadAndToPdf(com.ningdatech.file.entity.File file) { + OSS oss = new OSSClientBuilder().build(fileServerProperties.getAli().getEndpoint(), fileServerProperties.getAli().getAccessKeyId(), fileServerProperties.getAli().getAccessKeySecret()); + AtomAgent ha = new AtomAgent(WpsContant.WPS_CONVERT_URL_ONLINE); + try (OSSObject ossObject = oss.getObject(file.getBucket(), file.getPath()); + InputStream stream = ossObject.getObjectContent();) { + String fileName = null; + byte[] bytes = new byte[4096]; + int read; + //测试环境 转不了PDF 请求不了 WPS转换服务器 + if(BizConst.DEV.equals(active)){ + byte[] byt = new byte[stream.available()]; + stream.read(byt); + return byt; + }else if(BizConst.PRE.equals(active) || + BizConst.PROD.equals(active)){ + String filePath = WpsContant.FIX_FILE_PATH + file.getOriginalFileName(); + convert(stream,filePath); + //转换PDF + List fileList =new ArrayList(); + //2)、定义转换后的pdf文件输出流 + OutputStream out = null; + //3)、添加原文件到集合 + fileList.add(new File(filePath)); + //4)、赋值转换后的pdf文件输出流 + File pdfFile = new File(WpsContant.PDF_PATH); + out = new FileOutputStream(pdfFile); + //5)、调用方法,执行将多个文件转为pdf文件 + ha.OFDToPDF(fileList, out); + FileInputStream fileInputStream = new FileInputStream(pdfFile); + fileName = URLEncoder.encode(WpsContant.PDF_NAME, CharsetUtil.UTF_8); + for(File f : fileList){ + //用完就删 + f.deleteOnExit(); + } + byte[] byt = new byte[fileInputStream.available()]; + fileInputStream.read(byt); + return byt; + } + }catch (Exception e){ + log.error(e.getMessage()); + }finally { + oss.shutdown(); + try { + ha.close(); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + return null; + } + public static void convert(InputStream inputStream, String filePath) { try { File file = new File(filePath); diff --git a/pmapi/src/test/java/com/ningdatech/pmapi/file/ProvinceOssTest.java b/pmapi/src/test/java/com/ningdatech/pmapi/file/ProvinceOssTest.java index c1a4500..92242d3 100644 --- a/pmapi/src/test/java/com/ningdatech/pmapi/file/ProvinceOssTest.java +++ b/pmapi/src/test/java/com/ningdatech/pmapi/file/ProvinceOssTest.java @@ -1,7 +1,6 @@ package com.ningdatech.pmapi.file; -import org.apache.tomcat.util.http.fileupload.IOUtils; -import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory; +import com.ningdatech.pmapi.common.util.CommonInputStreamResource; import org.junit.Test; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -12,11 +11,10 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.multipart.commons.CommonsMultipartFile; + import java.io.File; import java.io.FileInputStream; -import org.springframework.web.multipart.MultipartFile; -import org.springframework.mock.web.MockMultipartFile; + import org.apache.http.entity.ContentType; import java.io.*; @@ -43,7 +41,7 @@ public class ProvinceOssTest { headers.setContentType(type); HttpEntity formEntity = new HttpEntity(params, headers); ResponseEntity res = restTemplate.postForEntity(url, formEntity, String.class); - System.out.println(res); + System.out.println(res.getBody()); } public static MultipartFile getMultipartFile(File file) {