@@ -1,4 +1,4 @@ | |||
package com.ningdatech.pmapi.file; | |||
package com.ningdatech.pmapi.common.util; | |||
import org.springframework.core.io.InputStreamResource; | |||
@@ -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; | |||
} | |||
} |
@@ -149,4 +149,7 @@ public class GovBizProjectApply implements Serializable { | |||
@ApiModelProperty("最后修改人") | |||
private String updateBy; | |||
@ApiModelProperty("立项依据材料PDF版") | |||
private String baseProjBasisFilePdf; | |||
} |
@@ -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"; | |||
} | |||
} |
@@ -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<String, Object> 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<MultiValueMap> formEntity = new HttpEntity(params, headers); | |||
ResponseEntity<OssApiResponse> 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(); | |||
} | |||
} |
@@ -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; | |||
/** | |||
* <p> | |||
* OssApiResponse - | |||
* </p> | |||
* | |||
* @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; | |||
} |
@@ -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; | |||
/** | |||
* <p> | |||
* OssApiResponse - | |||
* </p> | |||
* | |||
* @author ZPF | |||
* @since 14:29 2022/9/29 | |||
*/ | |||
@Data | |||
@NoArgsConstructor | |||
public class OssApiResponse<T> 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 <T> OssApiResponse<T> of(Integer respCode, String respMsg, T data) { | |||
return new OssApiResponse<T>(respCode, respMsg, data); | |||
} | |||
/** | |||
* 构造一个成功且不带数据的API返回 | |||
* | |||
* @return ApiResponse | |||
*/ | |||
public static <T> OssApiResponse<T> ofSuccess() { | |||
return ofSuccess(null); | |||
} | |||
/** | |||
* 构造一个成功且带数据的API返回 | |||
* | |||
* @param data 返回数据 | |||
* @return ApiResponse | |||
*/ | |||
public static <T> OssApiResponse<T> ofSuccess(T data) { | |||
return ofStatus(Status.OK, data); | |||
} | |||
/** | |||
* 构造一个成功且自定义消息的API返回 | |||
* | |||
* @param msg 返回内容 | |||
* @return ApiResponse | |||
*/ | |||
public static <T> OssApiResponse<T> ofMessage(String msg) { | |||
return of(Status.OK.getCode(), msg, null); | |||
} | |||
/** | |||
* 构造一个有状态的API返回 | |||
* | |||
* @param status 状态 {@link Status} | |||
* @return ApiResponse | |||
*/ | |||
public static <T> OssApiResponse<T> ofStatus(ApiStatus status) { | |||
return ofStatus(status, null); | |||
} | |||
/** | |||
* 构造一个有状态且带数据的API返回 | |||
* | |||
* @param status 状态 {@link Status} | |||
* @param data 返回数据 | |||
* @return ApiResponse | |||
*/ | |||
public static <T> OssApiResponse<T> ofStatus(ApiStatus status, T data) { | |||
return of(status.getCode(), status.getReasonPhrase(), data); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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<File> fileList =new ArrayList<File>(); | |||
//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); | |||
@@ -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<MultiValueMap> formEntity = new HttpEntity(params, headers); | |||
ResponseEntity<String> res = restTemplate.postForEntity(url, formEntity, String.class); | |||
System.out.println(res); | |||
System.out.println(res.getBody()); | |||
} | |||
public static MultipartFile getMultipartFile(File file) { | |||