Merge pull request 'lb:pdf文件合并功能' (#4) from yem_handsome_lb into main

Reviewed-on: #4
This commit is contained in:
yem_handsome_lb 2025-01-14 17:43:48 +08:00
commit 24ff73a10a

View File

@ -0,0 +1,306 @@
package yem.base.common.module.attach.dynamic;
import com.lowagie.text.Document;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfReader;
import kd.bos.cache.CacheFactory;
import kd.bos.context.RequestContext;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.resource.ResManager;
import kd.bos.entity.EntityMetadataCache;
import kd.bos.entity.MainEntityType;
import kd.bos.entity.datamodel.IDataModel;
import kd.bos.exception.KDBizException;
import kd.bos.fileservice.FileItem;
import kd.bos.fileservice.FileService;
import kd.bos.fileservice.FileServiceFactory;
import kd.bos.form.FormShowParameter;
import kd.bos.form.IFormView;
import kd.bos.form.control.AttachmentPanel;
import kd.bos.form.control.Control;
import kd.bos.form.control.EntryGrid;
import kd.bos.form.events.AfterDoOperationEventArgs;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.metadata.dao.MetaCategory;
import kd.bos.metadata.dao.MetadataDao;
import kd.bos.metadata.form.ControlAp;
import kd.bos.metadata.form.FormMetadata;
import kd.bos.metadata.form.control.AttachmentPanelAp;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.user.UserServiceHelper;
import kd.sdk.plugin.Plugin;
import yem.base.common.utils.FileUtil;
import yem.base.common.utils.YEM;
import java.io.*;
import java.net.URLDecoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* PDF 文件合并动态表单插件
* @author lib
* @date 2025年01月14日 下午 16:45:51
*/
public class PDFMergeDynamicPlugin extends AbstractFormPlugin implements Plugin {
@Override
public void afterCreateNewData(EventObject e) {
super.afterCreateNewData(e);
initData();
}
@Override
public void afterDoOperation(AfterDoOperationEventArgs e) {
super.afterDoOperation(e);
String operateKey = e.getOperateKey();
switch(operateKey){
case "refreshentry": // 刷新自动重新从父页面更新PDF文件明细
initData();
break;
default :
break;
}
}
/**
* PDF文件合并界面初始化
* */
private void initData(){
IFormView view = this.getView();
IDataModel model = view.getModel();
// 清除分录
model.deleteEntryData("yem_entryentity");
FormShowParameter formShowParameter = view.getFormShowParameter();
String attachKey = formShowParameter.getCustomParam("srcAttachKey");
if (YEM.isEmpty(attachKey))return;
IFormView parentView = view.getParentView();
if (parentView == null) return;
DynamicObject dataEntity = parentView.getModel().getDataEntity();// 源单实体
// 获取附件
AttachmentPanel panel = parentView.getControl(attachKey);
List<Map<String, Object>> attachs = panel.getAttachmentData();
DynamicObjectCollection entry = model.getEntryEntity("yem_entryentity");
for (Map<String, Object> attach:attachs){
String fileName = (String) attach.get("name");
String url = (String) attach.get("url");
if (YEM.isEmpty(fileName)) continue;
if (fileName.endsWith(".pdf") || fileName.endsWith(".PDF")){
int row = model.createNewEntryRow("yem_entryentity");
model.setValue("yem_attachmentname",fileName,row);
model.setValue("yem_url",url,row);
}
}
}
@Override
public void registerListener(EventObject e) {
super.registerListener(e);
this.addClickListeners("btnok","btncancel");
}
@Override
public void click(EventObject evt) {
super.click(evt);
IFormView view = this.getView();
IFormView parentView = view.getParentView();
Control source = (Control) evt.getSource();
String key = source.getKey();
// 获取需要合并的文件
EntryGrid treeEntryEntity = this.getControl("yem_entryentity");
int[] rows = treeEntryEntity.getSelectRows();
switch(key){
case "btnok":
if (rows.length == 0 ){
this.getView().showErrorNotification(ResManager.loadKDString("请先选择需要合并的附件!", "PDFMergeDynamicPlugin_0", "yem-base"));
return;
}
if (rows.length < 2 ){
this.getView().showErrorNotification(ResManager.loadKDString("请至少选择两个文件进行合并!", "PDFMergeDynamicPlugin_1", "yem-base"));
return;
}
Arrays.sort(rows);
try {
mergeCreateFile(rows);
} catch (IOException e) {
this.getView().showErrorNotification(ResManager.loadKDString("文件合并失败!", "PDFMergeDynamicPlugin_2", "yem-base"));
return;
}
view.returnDataToParent("success");
view.close();
break;
case "btncancel":
view.close();
break;
default:
break;
}
}
// 合并生成文件并回传至源单
private void mergeCreateFile(int[] rows) throws IOException {
// 获取源单数据
FormShowParameter formShowParameter = this.getView().getFormShowParameter();
String attachKey = formShowParameter.getCustomParam("targetAttachKey");
IFormView parentView = this.getView().getParentView();
if (YEM.isEmpty(attachKey) || parentView == null)return;
DynamicObject obj = parentView.getModel().getDataEntity();// 源单实体
SimpleDateFormat format = new SimpleDateFormat("HHmmss");
String date = format.format(new Date());
String newfilename = obj.getString("billno")+"_"+date+".pdf";
String formId = obj.getDataEntityType().getName();
//创建新的pdf文件作为合并的pdf文件
Document document = new Document();
PdfCopy pdfCopy=null;
FileUtil fileUtil = new FileUtil(formId);
File newfile = fileUtil.newFile(newfilename);
FileUtil.createNewFile(newfile);
FileOutputStream fileOutputStream = new FileOutputStream(newfile);
try {
pdfCopy = new PdfCopy(document, fileOutputStream);
document.open();
for (int i = 0; i < rows.length; i++) {
int row = rows[i];
String url = (String)this.getView().getModel().getValue("yem_url", row);
InputStream inputStream = null;
if (url.contains("serversForCache")){
inputStream = CacheFactory.getCommonCacheFactory().getTempFileCache().getInputStream(url);
} else {
String path = getPath(url);
inputStream = FileServiceFactory.getAttachmentFileService().getInputStream(path);
}
PdfReader pdfReader = new PdfReader(inputStream);
//循环原pdf文件的各页信息添加到新的pdf文件中
for (int f=1;f<=pdfReader.getNumberOfPages();f++){
pdfCopy.addPage(pdfCopy.getImportedPage(pdfReader,f));
pdfReader.close();
}
}
} catch (Exception e) {
fileOutputStream.close();
document.close();
throw new KDBizException(ResManager.loadKDString("合并文件失败!", "PDFMergeDynamicPlugin_3", "yem-base"));
}
document.close();
fileOutputStream.close();
DateFormat df = new SimpleDateFormat("yyyyMM");
String NewDateStr = df.format(new Date());
String path = "/" + RequestContext.get().getTenantId() +
"/" + RequestContext.get().getAccountId()+
"/" + NewDateStr +
"/" + formId + "/" + obj.getString("id") +
"/"+newfilename;
FileService fs = FileServiceFactory.getAttachmentFileService();
FileItem fi = new FileItem(newfilename, path, new FileInputStream(newfile.getPath()));
fi.setCreateNewFileWhenExists(true);
String url = fs.upload(fi);
List<Map<String,Object>>attachDataList= new ArrayList<>();
Map<String,Object>attachMap =new HashMap<>();
//获取附件inputstream上传到缓存服务
InputStream inputStream= FileServiceFactory.getAttachmentFileService().getInputStream(url);
attachMap.put("size",calculateSize(FileServiceFactory.getAttachmentFileService().getInputStream(url)));//size
String saveUrl=CacheFactory.getCommonCacheFactory().getTempFileCache().saveAsFullUrl(newfilename,
new BufferedInputStream(inputStream),2*3600);
attachMap.put("url", saveUrl);//url
attachMap.put("uid", UUID.randomUUID().toString());//uid
attachMap.put("name",newfilename);//name
attachMap.put("lastModified",new Date().getTime());//lastModified
attachMap.put("uploadTime",new Date().getTime());
attachMap.put("status","success");
long currentUserId = UserServiceHelper.getCurrentUserId();
DynamicObject user = BusinessDataServiceHelper.loadSingle(currentUserId, "bos_user");
attachMap.put("creator", user == null ? "金小蝶":user.getString("name"));
attachMap.put("description", "");//description
attachMap.put("type", "pdf");
attachMap.put("fattachmentpanel",attachKey);
attachMap.put("entityNum", "");
attachMap.put("billPkId", 0L);
attachMap.put("billno", "");
attachMap.put("client", "web");
attachMap.put("endProgress", true);
attachMap.put("filesource", 1);
attachDataList.add(attachMap);
AttachmentPanel control = this.getView().getParentView().getControl(attachKey);
control.upload(attachDataList);
this.getView().getParentView().updateView(attachKey);
}
/**
* 根据文件下载url截取相对路径
* @param url 文件下载url
* */
private String getPath(String url){
String path=null;
if (url.contains("path=")){
String[] paths = url.split("path=");
path=paths[1];
}else {
path=url;
}
try {
//url解码
path = URLDecoder.decode(path, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
//移除前面多余的//
if (path.startsWith("//")){
path = path.substring(2, path.length());
}
return path;
}
/**
* 根据文件流获取新文件的大小
* */
public static long calculateSize(InputStream inputStream) {
long size = 0;
byte[] buffer = new byte[4096];
int bytesRead;
try {
while ((bytesRead = inputStream.read(buffer)) != -1) {
size += bytesRead;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return size;
}
/**
* 获取源单实体所有附件面板的key
* @param formName 源单标识
* */
private List<String> getAttachControl(String formName){
MainEntityType entityType = EntityMetadataCache.getDataEntityType(formName);
FormMetadata taskMeta = (FormMetadata) MetadataDao.readRuntimeMeta(MetadataDao.getIdByNumber(
entityType.getName(), MetaCategory.Form), MetaCategory.Form);
List<ControlAp<?>> items = taskMeta.getItems();
// 附件面板标识集合
List<String> attachmentPanelAp = new ArrayList<>();
items.forEach(item ->{
if(item instanceof AttachmentPanelAp){
attachmentPanelAp.add(item.getKey());
}
});
return attachmentPanelAp;
}
}