添加pdf生成器

This commit is contained in:
2023-12-20 16:04:34 +08:00
parent 714f00423c
commit 7293446993
12 changed files with 466 additions and 18 deletions

View File

@@ -71,6 +71,12 @@
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>playwright</artifactId>
<version>1.40.0</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>

View File

@@ -130,25 +130,65 @@ public class FileService extends BaseService<FileEntity, FileRepository> {
}
String objectKey = fileEntity.getDirectory() + "/" + fileEntity.getObjectId();
String objectUrl = "";
// PutObjectResult putObjectResult =
// obsClient.putObject(
// hwCloudProperty.getObs().getBucketName(),
// objectKey,
// file.getInputStream());
//
// if (putObjectResult.getStatusCode() != 200) {
// throw new BizException("上传文件失败 %s".formatted(putObjectResult.toString()));
// }
// objectUrl = putObjectResult.getObjectUrl();
fileEntity.setPublicUrl(uploadToOSS(objectKey, file.getInputStream()));
this.save(fileEntity);
return getById(fileEntity.getId());
}
@SneakyThrows
public FileDto upload(
InputStream file,
String name,
String dir,
String sortKey,
String code,
String remarks) {
FileEntity fileEntity = new FileEntity();
fileEntity.setFileName(name);
fileEntity.setFileSize(Long.valueOf(file.available()));
fileEntity.setCode(code);
fileEntity.setRemarks(remarks);
try {
fileEntity.setSortKey(Integer.parseInt(sortKey));
} catch (Exception e) {
fileEntity.setSortKey(1);
}
fileEntity.setDirectory(
"%s/%s/%s"
.formatted(
activateProfile,
Ctx.currentUser().getOrganizationId(),
StringUtils.defaultIfBlank(dir, "public")));
InputStream inputStream = file;
fileEntity.setObjectId(
UUID.randomUUID() + "." + FilenameUtils.getExtension(name.replace(":", "_")));
try (inputStream) {
fileEntity.setMimeType(tika.detect(inputStream));
}
String objectKey = fileEntity.getDirectory() + "/" + fileEntity.getObjectId();
fileEntity.setPublicUrl(uploadToOSS(objectKey, file));
this.save(fileEntity);
return getById(fileEntity.getId());
}
private String uploadToOSS(String objectKey, InputStream inputStream) {
String objectUrl;
try {
com.aliyun.oss.model.PutObjectResult objectResult =
ossClient.putObject(
aliyunProperty.getOSS().getBucketName(),
objectKey,
file.getInputStream());
inputStream);
} catch (Exception e) {
log.warn("上传文件失败", e);
@@ -171,11 +211,6 @@ public class FileService extends BaseService<FileEntity, FileRepository> {
aliyunProperty.getOSS().getBucketName(),
ossRegion.getEndpoint(),
objectKey);
fileEntity.setPublicUrl(objectUrl);
this.save(fileEntity);
return getById(fileEntity.getId());
return objectUrl;
}
}

View File

@@ -0,0 +1,61 @@
package cn.lihongjie.coal.pdfGenerator.controller;
import cn.lihongjie.coal.annotation.OrgScope;
import cn.lihongjie.coal.annotation.SysLog;
import cn.lihongjie.coal.base.dto.CommonQuery;
import cn.lihongjie.coal.base.dto.IdRequest;
import cn.lihongjie.coal.pdfGenerator.dto.CreatePdfGeneratorDto;
import cn.lihongjie.coal.pdfGenerator.dto.GeneratePdfDto;
import cn.lihongjie.coal.pdfGenerator.dto.PdfGeneratorDto;
import cn.lihongjie.coal.pdfGenerator.dto.UpdatePdfGeneratorDto;
import cn.lihongjie.coal.pdfGenerator.service.PdfGeneratorService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
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.RestController;
@RestController
@RequestMapping("/pdfGenerator")
@SysLog(module = "Pdf生成器")
@Slf4j
@OrgScope
public class PdfGeneratorController {
@Autowired private PdfGeneratorService service;
@PostMapping("/create")
public PdfGeneratorDto create(@RequestBody CreatePdfGeneratorDto request) {
return this.service.create(request);
}
@PostMapping("/update")
public PdfGeneratorDto update(@RequestBody UpdatePdfGeneratorDto request) {
return this.service.update(request);
}
@PostMapping("/delete")
public Object delete(@RequestBody IdRequest request) {
this.service.delete(request);
return true;
}
@PostMapping("/getById")
public PdfGeneratorDto getById(@RequestBody IdRequest request) {
return this.service.getById(request.getId());
}
@PostMapping("/generate")
public PdfGeneratorDto generate(@RequestBody GeneratePdfDto request) {
return this.service.generate(request);
}
@PostMapping("/list")
public Page<PdfGeneratorDto> list(@RequestBody CommonQuery request) {
return this.service.list(request);
}
}

View File

@@ -0,0 +1,13 @@
package cn.lihongjie.coal.pdfGenerator.dto;
import cn.lihongjie.coal.base.dto.OrgCommonDto;
import lombok.Data;
@Data
public class CreatePdfGeneratorDto extends OrgCommonDto {
}

View File

@@ -0,0 +1,15 @@
package cn.lihongjie.coal.pdfGenerator.dto;
import cn.lihongjie.coal.base.dto.OrgCommonDto;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.Data;
@Data
public class GeneratePdfDto extends OrgCommonDto {
private String htmlUrl;
private String htmlText;
private ObjectNode options;
}

View File

@@ -0,0 +1,28 @@
package cn.lihongjie.coal.pdfGenerator.dto;
import cn.lihongjie.coal.base.dto.OrgCommonDto;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class PdfGeneratorDto extends OrgCommonDto {
private String htmlUrl;
private String htmlText;
private String pdfUrl;
private LocalDateTime startTime;
private LocalDateTime endTime;
private Long duration;
private String options;
}

View File

@@ -0,0 +1,8 @@
package cn.lihongjie.coal.pdfGenerator.dto;
import cn.lihongjie.coal.base.dto.OrgCommonDto;
import lombok.Data;
@Data
public class UpdatePdfGeneratorDto extends OrgCommonDto {}

View File

@@ -0,0 +1,46 @@
package cn.lihongjie.coal.pdfGenerator.entity;
import cn.lihongjie.coal.base.entity.OrgCommonEntity;
import jakarta.persistence.Entity;
import lombok.Data;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.Formula;
import java.time.LocalDateTime;
@Data
@Entity
public class PdfGeneratorEntity extends OrgCommonEntity {
private String htmlUrl;
private String htmlText;
private String pdfUrl;
private LocalDateTime startTime;
private LocalDateTime endTime;
private Long duration;
private String options;
@Comment("生成状态")
private String execStatus;
@Formula(
"(select i.name\n"
+ "from t_dictionary d,\n"
+ " t_dictionary_item i\n"
+ "where d.id = i.dictionary_id\n"
+ " and d.code = 'common.execStatus'\n"
+ " and i.code = exec_status)")
private String execStatusName;
}

View File

@@ -0,0 +1,25 @@
package cn.lihongjie.coal.pdfGenerator.mapper;
import cn.lihongjie.coal.base.mapper.BaseMapper;
import cn.lihongjie.coal.base.mapper.CommonMapper;
import cn.lihongjie.coal.pdfGenerator.dto.CreatePdfGeneratorDto;
import cn.lihongjie.coal.pdfGenerator.dto.GeneratePdfDto;
import cn.lihongjie.coal.pdfGenerator.dto.PdfGeneratorDto;
import cn.lihongjie.coal.pdfGenerator.dto.UpdatePdfGeneratorDto;
import cn.lihongjie.coal.pdfGenerator.entity.PdfGeneratorEntity;
import org.mapstruct.Mapper;
import org.mapstruct.control.DeepClone;
@Mapper(
componentModel = org.mapstruct.MappingConstants.ComponentModel.SPRING,
uses = {CommonMapper.class},
mappingControl = DeepClone.class)
public interface PdfGeneratorMapper
extends BaseMapper<
PdfGeneratorEntity,
PdfGeneratorDto,
CreatePdfGeneratorDto,
UpdatePdfGeneratorDto> {
PdfGeneratorEntity toEntity(GeneratePdfDto request);
}

View File

@@ -0,0 +1,9 @@
package cn.lihongjie.coal.pdfGenerator.repository;
import cn.lihongjie.coal.base.dao.BaseRepository;
import cn.lihongjie.coal.pdfGenerator.entity.PdfGeneratorEntity;
import org.springframework.stereotype.Repository;
@Repository
public interface PdfGeneratorRepository extends BaseRepository<PdfGeneratorEntity> {}

View File

@@ -0,0 +1,188 @@
package cn.lihongjie.coal.pdfGenerator.service;
import cn.lihongjie.coal.base.dto.CommonQuery;
import cn.lihongjie.coal.base.dto.IdRequest;
import cn.lihongjie.coal.base.service.BaseService;
import cn.lihongjie.coal.file.dto.FileDto;
import cn.lihongjie.coal.file.service.FileService;
import cn.lihongjie.coal.pdfGenerator.dto.CreatePdfGeneratorDto;
import cn.lihongjie.coal.pdfGenerator.dto.GeneratePdfDto;
import cn.lihongjie.coal.pdfGenerator.dto.PdfGeneratorDto;
import cn.lihongjie.coal.pdfGenerator.dto.UpdatePdfGeneratorDto;
import cn.lihongjie.coal.pdfGenerator.entity.PdfGeneratorEntity;
import cn.lihongjie.coal.pdfGenerator.mapper.PdfGeneratorMapper;
import cn.lihongjie.coal.pdfGenerator.repository.PdfGeneratorRepository;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.Playwright;
import com.microsoft.playwright.Response;
import jakarta.annotation.PreDestroy;
import lombok.Cleanup;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.ByteArrayInputStream;
import java.time.Duration;
import java.time.LocalDateTime;
@Service
@Slf4j
@Transactional
public class PdfGeneratorService extends BaseService<PdfGeneratorEntity, PdfGeneratorRepository> {
@Autowired FileService fileService;
@Autowired ObjectMapper objectMapper;
@Autowired private PdfGeneratorRepository repository;
@Autowired private PdfGeneratorMapper mapper;
@Autowired private ConversionService conversionService;
private Boolean chromeInit = false;
private Playwright playwright;
private Browser browser;
@PreDestroy
public void destroy() {
log.info("销毁chrome");
if (browser != null) {
browser.close();
}
if (playwright != null) {
playwright.close();
}
}
@SneakyThrows
public PdfGeneratorDto generate(GeneratePdfDto request) {
synchronized (this) {
LocalDateTime startTime = LocalDateTime.now();
if (!chromeInit) {
log.info("初始化chrome");
playwright = Playwright.create();
browser = playwright.chromium().launch();
chromeInit = true;
}
@Cleanup com.microsoft.playwright.Page page = browser.newPage();
if (StringUtils.isNotEmpty(request.getHtmlText())) {
page.setContent(request.getHtmlText());
} else if (StringUtils.isNotEmpty(request.getHtmlUrl())) {
Response response = page.navigate(request.getHtmlUrl());
log.info("访问{}返回{}", request.getHtmlUrl(), response.status());
} else {
throw new IllegalArgumentException("htmlText和htmlUrl不能同时为空");
}
com.microsoft.playwright.Page.PdfOptions pdfOptions = null;
if (request.getOptions() != null) {
pdfOptions =
objectMapper.treeToValue(
request.getOptions(),
com.microsoft.playwright.Page.PdfOptions.class);
}
PdfGeneratorEntity entity = mapper.toEntity(request);
boolean error = false;
String stackTrace = null;
byte[] pdf = null;
try {
pdf = page.pdf(pdfOptions);
} catch (Exception e) {
log.error("生成pdf失败", e);
stackTrace = ExceptionUtils.getStackTrace(e);
error = true;
}
if (pdf != null) {
FileDto generatePdf = null;
try {
generatePdf =
fileService.upload(
new ByteArrayInputStream(pdf),
request.getName(),
"generatePdf",
null,
null,
"");
} catch (Exception e) {
log.error("上传pdf失败", e);
error = true;
stackTrace = ExceptionUtils.getStackTrace(e);
}
if (!error) {
entity.setPdfUrl(generatePdf.getPublicUrl());
}
}
entity.setEndTime(LocalDateTime.now());
entity.setDuration(Duration.between(startTime, entity.getEndTime()).toMillis());
entity.setRemarks(stackTrace);
entity.setExecStatus(error ? "1" : "0");
this.save(entity);
return this.mapper.toDto(entity);
}
}
public PdfGeneratorDto create(CreatePdfGeneratorDto request) {
PdfGeneratorEntity entity = mapper.toEntity(request);
this.repository.save(entity);
return getById(entity.getId());
}
public PdfGeneratorDto update(UpdatePdfGeneratorDto request) {
PdfGeneratorEntity entity = this.repository.get(request.getId());
this.mapper.updateEntity(entity, request);
this.repository.save(entity);
return getById(entity.getId());
}
public void delete(IdRequest request) {
this.repository.deleteAllById(request.getIds());
}
public PdfGeneratorDto getById(String id) {
PdfGeneratorEntity entity = repository.get(id);
return mapper.toDto(entity);
}
public Page<PdfGeneratorDto> list(CommonQuery query) {
Page<PdfGeneratorEntity> page =
repository.findAll(
query.specification(conversionService),
PageRequest.of(
query.getPageNo(),
query.getPageSize(),
Sort.by(query.getOrders())));
return page.map(this.mapper::toDto);
}
}

View File

@@ -1703,6 +1703,20 @@
}
]
},
{
"code": "common.execStatus",
"name": "通用状态",
"item": [
{
"code": "0",
"name": "成功"
},
{
"code": "1",
"name": "失败"
}
]
},
{
"code": "loginUserHis.loginStatus",
"name": "登录状态",