使用 jaspersoft iReport导出多个pdf系列一1
Exporter.java
public interface Exporter {
/**
* 获取导出类型
* @return
*/
ExportTemplateEnum getTemplate();
/**
* 导出
* @param config@return
*/
ExportResultDTO export(ExportConfigDTO config);
}
ExporterFactory.java
@Component
public class ExporterFactory {
public static Map<String, Exporter> exporterMap = new HashMap<>(1 << 7);
@Autowired
private List<Exporter> exporters;
@PostConstruct
public void init() {
for (Exporter exporter : exporters) {
ExportTemplateEnum exportType = exporter.getTemplate();
if (exportType != null) {
exporterMap.put(exportType.getName(), exporter);
}
}
exporters = null;
}
public static Exporter getExporterByTemplate(String exportType) {
return exporterMap.get(exportType);
}
}
ExportTemplateEnum.java
/**
* 导出模板枚举
*
* @author mori
* @date 2022/2/14
*/
public enum ExportTemplateEnum {
DPD_PACKING_LIST("DPD Packing List", true);
private final String name;
private final boolean enabled;
ExportTemplateEnum(String name, boolean enabled) {
this.name = name;
this.enabled = enabled;
}
public String getName() {
return name;
}
public boolean isEnabled() {
return enabled;
}
public static ExportTemplateEnum getByName(String templateName) {
for (ExportTemplateEnum value : values()) {
if (Objects.equals(value.getName(), templateName)) {
return value;
}
}
return null;
}
}
BaseExporter.java
@Slf4j
public abstract class BaseExporter implements Exporter {
@Override
public ExportResultDTO export(ExportConfigDTO config) {
List<String> uuids = config.getUuids();
Integer exportType = config.getExportType();
SessionContext sessionContext = SessionContextUtil.getDubboSessionContext();
log.info("export sessionContext: {}", JSON.toJSONString(sessionContext));
if (Objects.equals(ExportTypeEnum.LINE_HAUL.getType(), exportType)) {
return exportByLineHaul(uuids, sessionContext);
}
if (Objects.equals(ExportTypeEnum.BAG.getType(), exportType)) {
return exportByBag(uuids, sessionContext);
}
if (Objects.equals(ExportTypeEnum.MANIFEST.getType(), exportType)) {
return exportByManifest(uuids, sessionContext);
}
if (Objects.equals(ExportTypeEnum.PARCEL.getType(), exportType)) {
return exportByParcel(uuids, sessionContext);
}
if (Objects.equals(ExportTypeEnum.SCAN.getType(), exportType)) {
return exportByParcel(uuids, sessionContext);
}
if (Objects.equals(ExportTypeEnum.TRUCKING.getType(), exportType)) {
return exportByTrucking(uuids, sessionContext);
}
return null;
}
protected ExportResultDTO exportByLineHaul(List<String> lineHaulUuids, SessionContext sessionContext) {
return ExportResultDTO.buildNotSupportResult();
}
protected ExportResultDTO exportByBag(List<String> bagUuids, SessionContext sessionContext) {
return ExportResultDTO.buildNotSupportResult();
}
protected ExportResultDTO exportByManifest(List<String> manifestUuids, SessionContext sessionContext) {
return ExportResultDTO.buildNotSupportResult();
}
protected ExportResultDTO exportByParcel(List<String> parcelUuids, SessionContext sessionContext) {
return ExportResultDTO.buildNotSupportResult();
}
protected ExportResultDTO exportByTrucking(List<String> truckingUuids, SessionContext sessionContext) {
return ExportResultDTO.buildNotSupportResult();
}
}
PdfExporter.java
public abstract class PdfExporter extends BaseExporter {
@Autowired
private LabelPrintClient labelPrintClient;
@Autowired
private AWSS3Util awss3Util;
@Autowired
private RedisUtil redisUtil;
public <T> ExportResultDTO exportToPdf(Map<String, List<T>> outMap, PageSizeEnum pageSize) {
if (MapUtils.isEmpty(outMap)) {
return null;
}
LabelReportDTO<CustomTemplateLabelDTO> labelReport = new LabelReportDTO<>();
List<CustomTemplateLabelDTO> labelList = new ArrayList<>();
for (Map.Entry<String, List<T>> entry : outMap.entrySet()) {
List<T> dataList = entry.getValue();
if (CollectionUtils.isNotEmpty(dataList)) {
CustomTemplateLabelDTO label = new CustomTemplateLabelDTO();
label.setTemplate(entry.getKey());
Object[] array = dataList.toArray();
label.setBeanArray(array);
label.setReportDataSourceType(ReportDataSourceEnum.BEAN_ARRAY.getValue());
labelList.add(label);
}
}
labelReport.setPageSize(pageSize.getId());
labelReport.setLabels(labelList);
//
CustomTemplateLabelResultDTO result = labelPrintClient.printAndMergePdfWithCustomTemplate(labelReport);
ExportResultDTO exportResultDTO = new ExportResultDTO();
exportResultDTO.setS3ObjectKey(result.getLabelKey());
exportResultDTO.setS3ObjectBucket(result.getLabelBucket());
exportResultDTO.setContentType(ExportConstant.PDF_CONTENT_TYPE);
exportResultDTO.setFilename(getFileName() + ".pdf");
return exportResultDTO;
}
public ExportResultDTO exportToPdf(PageSizeEnum pageSizeEnum, List<byte[]> bytesList, boolean top) {
byte[] bytes = LabelUtil.printAndMergePdf(pageSizeEnum, bytesList, top);
String labelKey = uploadLabelAndGetAutoKey(bytes);
ExportResultDTO exportResult = new ExportResultDTO();
exportResult.setS3ObjectKey(labelKey);
exportResult.setS3ObjectBucket(awss3Util.getTemplateBucket());
exportResult.setContentType(ExportConstant.PDF_CONTENT_TYPE);
exportResult.setFilename(getFileName() + ".pdf");
return exportResult;
}
public ExportResultDTO exportToPdf(float urx, float ury, List<byte[]> bytesList, boolean top) {
byte[] bytes = LabelUtil.printAndMergePdf(urx, ury, bytesList, top);
String labelKey = uploadLabelAndGetAutoKey(bytes);
ExportResultDTO exportResult = new ExportResultDTO();
exportResult.setS3ObjectKey(labelKey);
exportResult.setS3ObjectBucket(awss3Util.getTemplateBucket());
exportResult.setContentType(ExportConstant.PDF_CONTENT_TYPE);
exportResult.setFilename(getFileName() + ".pdf");
return exportResult;
}
public String uploadLabelAndGetAutoKey(byte[] bytes) {
String labelKey = redisUtil.getIncrementKeyByBiExport();
awss3Util.putBytesToLabelBucket(labelKey, bytes);
return labelKey;
}
protected abstract String getFileName();
public ExportResultDTO bytesToPdf(byte[] bytes, String filename) {
try {
String key = uploadLabelAndGetAutoKey(bytes);
return ExportResultDTO.builder().support(true).s3ObjectBucket(AWSS3Util.AWS_S3_BUCKET_DEFAULT).s3ObjectKey(key).contentType(ExportConstant.PDF_CONTENT_TYPE).filename(filename + ".pdf").build();
} catch (Exception e) {
throw new RuntimeException("Export excel failed.", e);
}
}
public ExportResultDTO exportToZip(List<PdfEntry> pdfEntries) {
try (ByteArrayOutputStream zipOut = new ByteArrayOutputStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(zipOut)) {
for (PdfEntry pdfZipEntry : pdfEntries) {
zipOutputStream.putNextEntry(new ZipEntry(pdfZipEntry.getEntryName()));
zipOutputStream.write(pdfZipEntry.getContent());
zipOutputStream.closeEntry();
}
zipOutputStream.closeEntry();
zipOutputStream.flush();
zipOutputStream.close();
String key = uploadLabelAndGetAutoKey(zipOut.toByteArray());
return ExportResultDTO.builder().support(true).s3ObjectKey(key).s3ObjectBucket(AWSS3Util.AWS_S3_BUCKET_DEFAULT).contentType(ExportConstant.ZIP_CONTENT_TYPE).filename(getFileName() + ".zip").build();
} catch (Exception e) {
throw new RuntimeException("Export zip failed.", e);
}
}
}
AirGoCustomsInvoiceExporter.java
@Slf4j
@Component
public class AirGoCustomsInvoiceExporter extends PdfExporter {
@Autowired
private LineHaulInnerService lineHaulInnerService;
@Autowired
private ParcelInnerService parcelInnerService;
@Autowired
private ParcelItemInnerService parcelItemInnerService;
private final String fileName = "air_go_customs_invoice";
@Override
public ExportTemplateEnum getTemplate() {
return ExportTemplateEnum.AIR_CO_CUSTOMS_INVOICE;
}
@Override
protected String getFileName() {
return fileName;
}
@Override
@ServiceResponse
protected ExportResultDTO exportByLineHaul(List<String> lineHaulUuids, SessionContext sessionContext) {
Map<String, List<AirGoCustomsInvoiceModel>> models = buildData(lineHaulUuids);
return exportToPdf(models, PageSizeEnum.A4);
}
private Map<String, List<AirGoCustomsInvoiceModel>> buildData(List<String> lineHaulUuids) {
List<LineHaul> lineHaulList = lineHaulInnerService.getLineHaulListByUuids(lineHaulUuids);
List<Parcel> parcelList = parcelInnerService.getParcelByLineHaulUuids(lineHaulUuids);
Map<String, List<Parcel>> parcelMap = new HashMap<>();
for (Parcel parcel : parcelList) {
String key = parcel.getLineHaulUuid();
List<Parcel> parcels = parcelMap.get(key);
if (parcels == null) {
parcelMap.put(key, new ArrayList<>(Collections.singletonList(parcel)));
}else{
parcels.add(parcel);
}
}
List<AirGoCustomsInvoiceModel> invoiceModels = new ArrayList<>(lineHaulList.size());
List<String> parcelUuids = parcelList.stream()
.map(Parcel::getUuid)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
Map<String, List<ParcelItemDTO>> parcelItemMap = parcelItemInnerService.getItemMapByParcelUuids(parcelUuids);
for (LineHaul lineHaul : lineHaulList) {
List<Parcel> parcels = parcelMap.get(lineHaul.getUuid());
AirGoCustomsInvoiceModel model = new AirGoCustomsInvoiceModel();
model.setMawb(lineHaul.getMawb());
model.setEtdTime(DateUtil.format(lineHaul.getFlightDate(), DateFormatConstants.SLASH_yyyy_MM_dd));
model.setQty(String.valueOf(parcels.size()));
List<AirGoItemModel> itemModels = new ArrayList<>(parcels.size());
BigDecimal totalValue = new BigDecimal(0l);
for (Parcel parcel : parcels) {
AirGoItemModel itemModel = new AirGoItemModel();
itemModel.setTrackingNo(parcel.getTrackingNo());
itemModel.setQty("1");
List<ParcelItemDTO> parcelItems = parcelItemMap.get(parcel.getUuid());
StringBuilder sb = new StringBuilder();
Double value = new Double(0l);
int maxCount = 0;
String hsCodeMax = "";
for(ParcelItemDTO parcelItem : parcelItems){
if (StringUtils.isNotEmpty(parcelItem.getDescription())) {
sb.append(parcelItem.getDescription()).append(",");
}
value += parcelItem.getTotalValue();
if(parcelItem.getItemCount() > maxCount){
String hsCode = parcelItem.getHsCode();
if(!"".equals(hsCode)){
hsCode = parcelItem.getHsCode().length() > 8 ? hsCode.substring(0, 8) : hsCode;
}
hsCodeMax = hsCode;
}
}
String description = sb.toString();
description = "".equals(description) ? description : description.substring(0, description.length() - 1);
itemModel.setDescription(description);
itemModel.setHsCode(hsCodeMax);
itemModel.setTotalValue(String.valueOf(value));
itemModels.add(itemModel);
}
model.setTotalValue(totalValue.toString());
model.setItems(itemModels);
invoiceModels.add(model);
}
Map<String, List<AirGoCustomsInvoiceModel>> dataMap = new HashMap<>();
dataMap.put("air_go_customs_invoice", invoiceModels);
return dataMap;
}
}
LabelPrintServiceImpl.java 中的 printAndMergePdfWithCustomTemplate()方法
@DubboService
public class LabelPrintServiceImpl implements LabelPrintService {
private static final Logger log = LoggerFactory.getLogger(LabelPrintServiceImpl.class);
/**
* 10x10页面大小
*/
private static final Rectangle RECTANGLE_PAGE_SIZE_10X10 = new RectangleReadOnly(292, 292);
/**
* 10x15页面大小
*/
private static final Rectangle RECTANGLE_PAGE_SIZE_10X15 = new RectangleReadOnly(297, 430);
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private LabelTypeInnerService labelTypeInnerService;
@Autowired
private Environment env;
@Value("${label.bucket}")
private String labelBucket;
@ServiceResponse
@Override
public ServiceResult<String> printAndMergePdfWithData(LabelReportDTO<DataLabelDTO> labelReport) {
return ServiceResult.ok(printAndMergePdfLabelReportWithData(labelReport));
}
@ServiceResponse
@Override
public ServiceResult<String> printAndMergePdfWithTemplate(LabelReportDTO<TemplateLabelDTO> labelReport) {
labelReport.setMerged(true);
labelReport.setLabelFormat(LabelFormatEnum.PDF.getCode());
List<PrintLabelResultDTO> printLabelResultList = printLabelReportWithTemplate(labelReport);
String labelKey = Optional.of(printLabelResultList)
.map(a -> a.get(0))
.map(PrintLabelResultDTO::getLabelKeys)
.map(a -> a.get(0))
.filter(StringUtils::isNotBlank)
.orElseThrow(() -> new ErrorCodeException(LabelErrorCode.PRINT_LABEL_ERROR, "Print label result is empty."));
return ServiceResult.ok(labelKey);
}
@ServiceResponse
@Override
public ServiceResult<List<PrintLabelResultDTO>> printWithTemplate(LabelReportDTO<TemplateLabelDTO> labelReport) {
List<PrintLabelResultDTO> printLabelResult = printLabelReportWithTemplate(labelReport);
return ServiceResult.ok(printLabelResult);
}
@ServiceResponse
@Override
public ServiceResult<String> printPackingListWithTemplate(List<String> parcelIdList) {
if (CollectionUtils.isEmpty(parcelIdList)) {
throw new ErrorCodeException(LabelErrorCode.PRINT_LABEL_ERROR, "Parcel list is empty.");
}
int size = parcelIdList.size();
TemplateExporter pdfTemplateExporter = TemplateExporterFactory.getPdfTemplateExporter();
if (Objects.isNull(pdfTemplateExporter)) {
throw new ErrorCodeException(LabelErrorCode.PRINT_LABEL_ERROR, "Template exporter not found, label format not support.");
}
List<byte[]> allLabelBytes = new ArrayList<>(size);
// 只打印拣货清单, 此接口固定10x15格式
String packingListTemplate = labelTypeInnerService.getPackingListTemplateName(PageSizeEnum.SIZE_10X15);
for (String parcelId : parcelIdList) {
Map<String, Object> templateParameters = new HashMap<>(1 << 1);
templateParameters.put("PARCEL_UUID", parcelId);
byte[] packingListTemplateBytes = pdfTemplateExporter.export(packingListTemplate, templateParameters);
allLabelBytes.add(packingListTemplateBytes);
}
// 单张直接打印,多张使用10x15合并
byte[] pdfBytes;
if (allLabelBytes.size() == 1) {
pdfBytes = allLabelBytes.get(0);
} else {
pdfBytes = pdfTemplateExporter.merge(RECTANGLE_PAGE_SIZE_10X15, allLabelBytes);
}
// 上传s3
String key = uploadLabel2S3(pdfBytes);
return ServiceResult.ok(key);
}
@ServiceResponse
@Override
public ServiceResult<CustomTemplateLabelResultDTO> printAndMergePdfWithCustomTemplate(LabelReportDTO<CustomTemplateLabelDTO> labelReport) {
List<CustomTemplateLabelDTO> labels = labelReport.getLabels();
if (CollectionUtils.isEmpty(labels)) {
throw new ErrorCodeException(LabelErrorCode.PRINT_LABEL_ERROR, "label list is empty.");
}
PdfExporter templateExporter = TemplateExporterFactory.getPdfTemplateExporter();
if (Objects.isNull(templateExporter)) {
throw new ErrorCodeException(LabelErrorCode.PRINT_LABEL_ERROR, "Template exporter not found, label format not support.");
}
int size = labels.size();
List<byte[]> allLabelBytes = new ArrayList<>(size);
for (CustomTemplateLabelDTO label : labels) {
String template = label.getTemplate();
Map<String, Object> parameters = label.getParameters();
Integer reportDataSourceType = label.getReportDataSourceType();
byte[] bytes;
if (Objects.equals(reportDataSourceType, ReportDataSourceEnum.BEAN_ARRAY.getValue())) {
Object[] beanArray = label.getBeanArray();
bytes = templateExporter.exportBean(template, beanArray);
} else {
bytes = templateExporter.export(template, parameters);
}
allLabelBytes.add(bytes);
}
// 打印页面尺寸
PageSizeEnum pageSize = PageSizeEnum.getById(labelReport.getPageSize());
Rectangle rectangle = getRectangleByPageSize(pageSize);
byte[] pdfBytes = templateExporter.merge(rectangle, allLabelBytes, false);
// 上传s3
String labelKey = uploadLabel2S3(pdfBytes);
CustomTemplateLabelResultDTO result = new CustomTemplateLabelResultDTO(labelBucket, labelKey);
return ServiceResult.ok(result);
}
/**
* 自定义数据源,合并打印pdf
*
* @param labelReport
* @return
*/
public String printAndMergePdfLabelReportWithData(LabelReportDTO<DataLabelDTO> labelReport) {
// 打印标签模板列表
List<DataLabelDTO> labels = labelReport.getLabels();
if (CollectionUtils.isEmpty(labels)) {
throw new ErrorCodeException(LabelErrorCode.PRINT_LABEL_ERROR, "label list is empty.");
}
int size = labels.size();
TemplateExporter pdfTemplateExporter = TemplateExporterFactory.getPdfTemplateExporter();
// 打印页面尺寸
PageSizeEnum pageSize = PageSizeEnum.getById(labelReport.getPageSize());
// 多个标签的pdf字节数组
List<byte[]> allLabelBytes = new ArrayList<>(size);
for (DataLabelDTO label : labels) {
// 打印单个标签
List<byte[]> labelBytes = exportBeanReport(label, pageSize, pdfTemplateExporter);
allLabelBytes.addAll(labelBytes);
}
return mergeExportAndUpload2S3(allLabelBytes, pageSize, pdfTemplateExporter);
}
/**
* 内嵌sql的template,打印报表
*
* @param labelReport 标签报表
* @return 打印结果
*/
private List<PrintLabelResultDTO> printLabelReportWithTemplate(LabelReportDTO<TemplateLabelDTO> labelReport) {
List<TemplateLabelDTO> labels = labelReport.getLabels();
// 检查label列表
if (CollectionUtils.isEmpty(labels)) {
throw new ErrorCodeException(LabelErrorCode.PRINT_LABEL_ERROR, "label list is empty.");
}
// 打印label格式
String labelFormat = Optional.ofNullable(labelReport.getLabelFormat())
.map(String::trim)
.filter(StringUtils::isNotBlank)
.map(String::toUpperCase)
.orElse(LabelFormatEnum.PDF.getCode());
// 根据格式获取模板导出器
TemplateExporter templateExporter = TemplateExporterFactory.getTemplateExporterByLabelFormat(labelFormat);
if (Objects.isNull(templateExporter)) {
throw new ErrorCodeException(LabelErrorCode.PRINT_LABEL_ERROR, "Template exporter not found, label format not support.");
}
boolean merged = Optional.ofNullable(labelReport.getMerged()).orElse(false);
if (!templateExporter.supportMerge()) {
// 该类型不支持合并打印
merged = false;
}
// 打印页面尺寸
PageSizeEnum pageSize = PageSizeEnum.getById(labelReport.getPageSize());
if (merged) {
// all label merged
return printAndMergeAllTemplateLabel(labels, pageSize, templateExporter);
} else {
return printAndSplitTemplateLabel(labels, pageSize, templateExporter, labelFormat);
}
}
/**
* template label合并打印
*
* @param labels
* @param pageSize
* @param templateExporter
* @return
*/
private List<PrintLabelResultDTO> printAndMergeAllTemplateLabel(List<TemplateLabelDTO> labels, PageSizeEnum pageSize, TemplateExporter templateExporter) {
// 多个标签的pdf字节数组
// int size = labels.size();
// List<byte[]> allLabelBytes = new ArrayList<>(size);
// for (TemplateLabelDTO label : labels) {
// List<byte[]> labelBytes = exportReport(label, pageSize, templateExporter, true);
// allLabelBytes.addAll(labelBytes);
// }
// String labelKey = mergeExportAndUpload2S3(allLabelBytes, pageSize, templateExporter);
List<PrintBytesDTO> printBytesDTOS = new ArrayList<>(labels.size());
for (TemplateLabelDTO label : labels) {
List<byte[]> labelBytes = exportReport(label, pageSize, templateExporter, true);
printBytesDTOS.add(new PrintBytesDTO(labelBytes, label.getAlignCenter()));
}
String labelKey = mergeExportAndUpload2S3Ex(printBytesDTOS, pageSize, templateExporter);
PrintLabelResultDTO mergedResult = new PrintLabelResultDTO();
mergedResult.setLabelKeys(Collections.singletonList(labelKey));
return Collections.singletonList(mergedResult);
}
/**
* template label 拆分打印
*
* @param labels
* @param pageSize
* @param templateExporter
* @param labelFormat
* @return
*/
private List<PrintLabelResultDTO> printAndSplitTemplateLabel(List<TemplateLabelDTO> labels, PageSizeEnum pageSize,
TemplateExporter templateExporter, String labelFormat) {
// 下面是拆分打印的实现部分
List<PrintLabelResultDTO> resultList = new ArrayList<>();
for (TemplateLabelDTO label : labels) {
PrintLabelResultDTO res = new PrintLabelResultDTO();
res.setLabelUuid(label.getLabelUuid());
try {
List<String> labelKeys = new ArrayList<>();
if (templateExporter.supportMerge()) {
// 单个label merge
List<byte[]> labelBytes = exportReport(label, pageSize, templateExporter, true);
String labelKey = mergeExportAndUpload2S3(labelBytes, pageSize, templateExporter);
labelKeys.add(labelKey);
} else {
// 拆分打印的base64Label不需要再次上传,可以提前添加
List<String> base64LabelKeys = label.getBase64LabelKeys();
if (CollectionUtils.isNotEmpty(base64LabelKeys)) {
labelKeys.addAll(base64LabelKeys);
}
List<byte[]> labelBytes = exportReport(label, pageSize, templateExporter, false);
if (CollectionUtils.isNotEmpty(labelBytes)) {
List<String> keys = uploadLabel2S3(labelBytes);
if (CollectionUtils.isNotEmpty(keys)) {
labelKeys.addAll(keys);
}
}
}
res.setLabelKeys(labelKeys);
res.setSuccess(true);
} catch (Exception e) {
log.error("Print label error,label uuid :" + label.getLabelUuid(), e);
res.setSuccess(false);
res.setErrorMessage(e.getMessage());
}
resultList.add(res);
}
return resultList;
}
private List<byte[]> exportReport(TemplateLabelDTO label, PageSizeEnum pageSize, TemplateExporter templateExporter, boolean needBase64Labels) {
List<byte[]> labelBytes = new ArrayList<>();
List<String> base64LabelKeys = label.getBase64LabelKeys();
boolean printBase64Label = CollectionUtils.isNotEmpty(base64LabelKeys) && needBase64Labels;
// print base64 label
if (printBase64Label) {
List<byte[]> bytes = exportBase64LabelKeysToBytes(base64LabelKeys);
labelBytes.addAll(bytes);
}
// 打印了base64Label就不需要打印标签主体部分
List<byte[]> bytes = exportJasperReportTemplateToBytes(label, pageSize, templateExporter, !printBase64Label);
labelBytes.addAll(bytes);
return labelBytes;
}
/**
* 从S3下载base64 label,导出为字节数组
*
* @param base64LabelKeys
* @return
*/
private List<byte[]> exportBase64LabelKeysToBytes(List<String> base64LabelKeys) {
if (CollectionUtils.isEmpty(base64LabelKeys)) {
return new ArrayList<>();
}
int size = base64LabelKeys.size();
List<byte[]> labelBytes = new ArrayList<>(size);
for (String labelKey : base64LabelKeys) {
byte[] base64Label = AWSS3Client.getObjectAsBytes(AWSS3Helper.getS3ClientByEnv(env), labelBucket, labelKey);
if (Objects.nonNull(base64Label)) {
labelBytes.add(base64Label);
} else {
throw new ErrorCodeException(LabelErrorCode.PRINT_LABEL_ERROR, "Base64 label print failed, label from S3 download error.");
}
}
return labelBytes;
}
/**
* 导出jasper report模板为字节数组
*
* @param label
* @param pageSize
* @param templateExporter
* @param printLabelBodyTemplate
* @return
*/
private List<byte[]> exportJasperReportTemplateToBytes(TemplateLabelDTO label, PageSizeEnum pageSize, TemplateExporter templateExporter, boolean printLabelBodyTemplate) {
List<byte[]> labelBytes = new ArrayList<>();
LabelTypeDTO labelType = getLabelType(label.getLabelType());
// 传入报表固定的两个参数
Map<String, Object> templateParameters = new HashMap<>(1 << 2);
String labelUuid = label.getLabelUuid();
templateParameters.put("LABEL_UUID", labelUuid);
String parcelUuid = label.getParcelUuid();
templateParameters.put("PARCEL_UUID", parcelUuid);
// 是否打印标签主体部分
if (printLabelBodyTemplate) {
String bodyTemplate = labelTypeInnerService.getLabelTemplateName(labelType, pageSize);
byte[] bodyBytes = templateExporter.export(bodyTemplate, templateParameters);
if (Objects.nonNull(bodyBytes)) {
labelBytes.add(bodyBytes);
}
}
// 是否打印拣货清单
Boolean printPackingList = Optional.ofNullable(label.getPrintPackingList()).orElse(false);
// 是否打印自定义拣货清单
boolean printCustomPackingList = labelTypeInnerService.needPrintCustomPackingList(labelType, pageSize);
if (!printPackingList && !printCustomPackingList) {
return labelBytes;
}
// 自定义拣货清单模板
String customPackingListTemplate = null;
// 中间如果需要打印自定义拣货清单模板,在body与公共拣货清单之间打印
if (printCustomPackingList) {
customPackingListTemplate = labelTypeInnerService.getCustomPackingListTemplate(pageSize, labelType);
if (StringUtils.isNotBlank(customPackingListTemplate)) {
// 自定义拣货清单不为空,进行打印
byte[] customPackingListBytes = templateExporter.export(customPackingListTemplate, templateParameters);
labelBytes.add(customPackingListBytes);
}
}
// 另外需要打印公共的拣货清单
if (printPackingList) {
String packingListTemplate = labelTypeInnerService.getPackingListTemplateName(pageSize);
// 没有打印过自定义模板或者公共打印模板与自定义不相同
if (!Objects.equals(customPackingListTemplate, packingListTemplate)) {
byte[] packingListTemplateBytes = templateExporter.export(packingListTemplate, templateParameters);
labelBytes.add(packingListTemplateBytes);
}
}
return labelBytes;
}
/**
* 根据标签类型id获取标签类型对象
*
* @param labelTypeId
* @return
*/
private LabelTypeDTO getLabelType(Integer labelTypeId) {
LabelTypeDTO labelType = labelTypeInnerService.getLabelTypeById(labelTypeId);
if (Objects.isNull(labelType)) {
log.error("Label type not found, label type: {}.", labelTypeId);
throw new ErrorCodeException(LabelErrorCode.PRINT_LABEL_ERROR,
String.format("Label type not found, label type: %s.", labelTypeId));
}
return labelType;
}
/**
* 将pdf按照页面尺寸合并为一张导出并上传至s3
*
* @param allLabelBytes 所以label的pdf字节数组
* @param pageSize 页面大小
* @return s3 object key
*/
private String mergeExportAndUpload2S3(List<byte[]> allLabelBytes, PageSizeEnum pageSize, TemplateExporter templateExporter) {
// 获取打印页面大小,合并导出pdf
Rectangle rectangle = getRectangleByPageSize(pageSize);
byte[] pdfBytes = null;
if (rectangle == PageSize.A4) {
// 如果是A4大小,需要根据页面宽高合并
pdfBytes = templateExporter.autoMerge(rectangle, allLabelBytes);
} else {
// 其他情况,直接合并
pdfBytes = templateExporter.merge(rectangle, allLabelBytes);
}
// 上传s3
return uploadLabel2S3(pdfBytes);
}
/**
* 将pdf按照页面尺寸合并为一张导出并上传至s3
*
* @param printBytesDTOList 所以label的pdf字节数组和对齐方式
* @param pageSize 页面大小
* @return s3 object key
*/
private String mergeExportAndUpload2S3Ex(List<PrintBytesDTO> printBytesDTOList, PageSizeEnum pageSize, TemplateExporter templateExporter) {
// 获取打印页面大小,合并导出pdf
Rectangle rectangle = getRectangleByPageSize(pageSize);
byte[] pdfBytes = null;
List<byte[]> allLabelBytes = new ArrayList<>();
for (PrintBytesDTO printBytesDTO : printBytesDTOList) {
allLabelBytes.addAll(printBytesDTO.getLabelBytes());
}
if (rectangle == PageSize.A4) {
// 如果是A4大小,需要根据页面宽高合并
pdfBytes = templateExporter.autoMerge(rectangle, allLabelBytes);
} else {
// 其他情况,直接合并
if (templateExporter instanceof PdfExporter) {
pdfBytes = ((PdfExporter) templateExporter).mergeWithAlign(rectangle, printBytesDTOList);
} else {
pdfBytes = templateExporter.merge(rectangle, allLabelBytes);
}
}
// 上传s3
return uploadLabel2S3(pdfBytes);
}
/**
* 使用bean数据源打印report,
*
* @param label
* @param pageSize
* @param templateExporter
* @return
*/
private List<byte[]> exportBeanReport(DataLabelDTO label, PageSizeEnum pageSize, TemplateExporter templateExporter) {
List<String> base64LabelKeys = label.getBase64LabelKeys();
// 打印base64编码label
List<byte[]> bytes = exportBase64LabelKeysToBytes(base64LabelKeys);
List<byte[]> labelBytes;
if (CollectionUtils.isNotEmpty(bytes)) {
labelBytes = new ArrayList<>(bytes);
} else {
labelBytes = new ArrayList<>();
}
LabelTypeDTO labelType = getLabelType(label.getLabelType());
LabelBodyDataDTO labelBodyData = label.getLabelBodyData();
// 打印标签主体
if (Objects.nonNull(labelBodyData)) {
String bodyTemplate = labelTypeInnerService.getLabelTemplateName(labelType, pageSize);
byte[] bodyBytes = templateExporter.exportBean(bodyTemplate, new Object[]{labelBodyData});
if (Objects.nonNull(bodyBytes)) {
labelBytes.add(bodyBytes);
}
}
PackingListDataDTO packingListData = label.getPackingListData();
// 打印拣货清单
if (Objects.nonNull(packingListData)) {
String packingListTemplate = labelTypeInnerService.getPackingListTemplateName(pageSize);
byte[] packingListBytes = templateExporter.exportBean(packingListTemplate, new Object[]{packingListData});
if (Objects.nonNull(packingListBytes)) {
labelBytes.add(packingListBytes);
}
}
return labelBytes;
}
/**
* 根据页面大小获取打印形状
*
* @param pageSize 页面大小
* @return 页面尺寸
*/
private Rectangle getRectangleByPageSize(PageSizeEnum pageSize) {
if (pageSize == PageSizeEnum.DEFAULT || pageSize == PageSizeEnum.SIZE_10X15) {
return RECTANGLE_PAGE_SIZE_10X15;
}
if (pageSize == PageSizeEnum.A4) {
return PageSize.A4;
}
if (pageSize == PageSizeEnum.SIZE_10X10) {
return RECTANGLE_PAGE_SIZE_10X10;
}
return RECTANGLE_PAGE_SIZE_10X15;
}
/**
* label 上传至s3
*
* @return s3 object key
*/
private String uploadLabel2S3(byte[] bytes) {
// redis自增生成key
String key = getLabelIncrementKey();
// 上传到s3,放到label/目录下
key = S3ObjectTypeEnum.LABEL.getPrefix() + key;
boolean uploadComplete = AWSS3Client.putBytes(AWSS3Helper.getS3ClientByEnv(env), labelBucket, key, bytes);
if (!uploadComplete) {
throw new ErrorCodeException(LabelErrorCode.PRINT_LABEL_ERROR, "S3 upload failed.");
}
return key;
}
private List<String> uploadLabel2S3(List<byte[]> labelBytes) {
if (CollectionUtils.isEmpty(labelBytes)) {
return new ArrayList<>();
}
int size = labelBytes.size();
List<String> labelKeys = new ArrayList<>(size);
for (byte[] labelByte : labelBytes) {
String labelKey = uploadLabel2S3(labelByte);
labelKeys.add(labelKey);
}
return labelKeys;
}
private String getLabelIncrementKey() {
StringBuilder key = new StringBuilder(CacheKey.LABEL_PRINT);
// 加上当前时间戳
key.append(SplitConstants.PERIOD).append(System.currentTimeMillis());
String redisKey = key.toString();
Long serialNo = redisTemplate.opsForValue().increment(redisKey);
// 1秒后过期
redisTemplate.expire(redisKey, Duration.ofSeconds(1));
key.append(SplitConstants.PERIOD).append(serialNo);
return key.toString();
}
}