使用 jaspersoft iReport导出多个pdf系列一1

使用 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();
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值