美文网首页springbootJava web
UReport导出PDF添加文字水印和图片水印

UReport导出PDF添加文字水印和图片水印

作者: 任未然 | 来源:发表于2020-09-09 11:14 被阅读0次

    一. 概述

    在后台管理系统中, 经常会遇到各种报表开发, 其中比较有名开源的报表框架UReport2, 了解UReport2可以访问官网URport2教程, 本文主要介绍拓展ureport2输出pdf添加水印

    二. 说明

    通过查看官网介绍, 可得知ExportManager.exportPdf() 是输出pdf的接口方法, 那么就进一步看看这个方法的实现, 然后改造


    重写源码结构

    2.1 覆盖源码实现类PdfProducer

    /*******************************************************************************
     * Copyright 2017 Bstek
     * 
     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
     * use this file except in compliance with the License.  You may obtain a copy
     * of the License at
     * 
     *   http://www.apache.org/licenses/LICENSE-2.0
     * 
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
     * License for the specific language governing permissions and limitations under
     * the License.
     ******************************************************************************/
    package com.bstek.ureport.export.pdf;
    
    import com.bstek.ureport.build.paging.Page;
    import com.bstek.ureport.chart.ChartData;
    import com.bstek.ureport.definition.Alignment;
    import com.bstek.ureport.definition.CellStyle;
    import com.bstek.ureport.definition.Orientation;
    import com.bstek.ureport.definition.Paper;
    import com.bstek.ureport.exception.ReportComputeException;
    import com.bstek.ureport.export.FullPageData;
    import com.bstek.ureport.export.PageBuilder;
    import com.bstek.ureport.export.Producer;
    import com.bstek.ureport.model.Image;
    import com.bstek.ureport.model.*;
    import com.bstek.ureport.utils.ImageUtils;
    import com.bstek.ureport.utils.UnitUtils;
    import com.itextpdf.text.*;
    import com.itextpdf.text.pdf.PdfPCell;
    import com.itextpdf.text.pdf.PdfPTable;
    import com.itextpdf.text.pdf.PdfWriter;
    import org.apache.commons.io.IOUtils;
    import org.apache.commons.lang.StringUtils;
    
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    
    /**
     * @author Jacky.gao
     * @since 2017年3月10日
     */
    public class PdfProducer implements Producer {
        @Override
        public void produce(Report report,OutputStream outputStream) {
            Paper paper=report.getPaper();
            int width=paper.getWidth();
            int height=paper.getHeight();
            Rectangle pageSize=new RectangleReadOnly(width,height);
            if(paper.getOrientation().equals(Orientation.landscape)){
                pageSize=pageSize.rotate();         
            }
            int leftMargin=paper.getLeftMargin();
            int rightMargin=paper.getRightMargin();
            int topMargin=paper.getTopMargin();
            int bottomMargin=paper.getBottomMargin();
            Document document=new Document(pageSize,leftMargin,rightMargin,topMargin,bottomMargin);
            try{
                PdfWriter writer=PdfWriter.getInstance(document,outputStream);
                PageHeaderFooterEvent headerFooterEvent=new PageHeaderFooterEvent(report);
                writer.setPageEvent(headerFooterEvent);
                document.open();
                List<Column> columns=report.getColumns();
                List<Integer> columnsWidthList=new ArrayList<Integer>();
                int[] intArr=buildColumnSizeAndTotalWidth(columns,columnsWidthList);
                int colSize=intArr[0],totalWidth=intArr[1];
                int[] columnsWidth=new int[columnsWidthList.size()];
                for(int i=0;i<columnsWidthList.size();i++){
                    columnsWidth[i]=columnsWidthList.get(i);
                }
                FullPageData pageData=PageBuilder.buildFullPageData(report);
                List<List<Page>> list=pageData.getPageList();
                if(list.size()>0){
                    int columnCount=paper.getColumnCount();
                    int w=columnCount*totalWidth+(columnCount-1)*paper.getColumnMargin();
                    int size=columnCount+(columnCount-1);
                    int[] widths=new int[size];
                    for(int i=0;i<size;i++){
                        int mode=(i+1)%2;
                        if(mode==0){
                            widths[i]=paper.getColumnMargin();                      
                        }else{
                            widths[i]=totalWidth;                   
                        }
                    }
                    float tableHeight=pageSize.getHeight()-paper.getTopMargin()-paper.getBottomMargin();
                    Map<Row, Map<Column, Cell>> cellMap=report.getRowColCellMap();
                    for(List<Page> pages:list){
                        PdfPTable table=new PdfPTable(size);
                        table.setLockedWidth(true);
                        table.setTotalWidth(w);
                        table.setWidths(widths);
                        table.setHorizontalAlignment(Element.ALIGN_LEFT);
                        int ps=pages.size();
                        for(int i=0;i<ps;i++){
                            if(i>0){
                                PdfPCell pdfMarginCell=new PdfPCell();
                                pdfMarginCell.setBorder(Rectangle.NO_BORDER);
                                table.addCell(pdfMarginCell);
                            }
                            Page page=pages.get(i);
                            
                            PdfPTable childTable=new PdfPTable(colSize);
                            childTable.setLockedWidth(true);
                            childTable.setTotalWidth(totalWidth);
                            childTable.setWidths(columnsWidth);
                            childTable.setHorizontalAlignment(Element.ALIGN_LEFT);
                            List<Row> rows=page.getRows();
                            for(Row row:rows){
                                Map<Column,Cell> colMap=cellMap.get(row);
                                if(colMap==null){
                                    continue;
                                }
                                for(Column col:columns){
                                    if(col.getWidth()<1){
                                        continue;
                                    }
                                    Cell cell=colMap.get(col);
                                    if(cell==null){
                                        continue;
                                    }
                                    int cellHeight=buildCellHeight(cell,rows);
                                    PdfPCell pdfcell=buildPdfPCell(cell,cellHeight);
                                    childTable.addCell(pdfcell);
                                }
                            }
                            float childTableHeight=childTable.calculateHeights();
                            if(tableHeight>childTableHeight){
                                for(int j=0;j<columns.size();j++){
                                    PdfPCell lastCell=new PdfPCell();
                                    lastCell.setBorder(Rectangle.NO_BORDER);
                                    childTable.addCell(lastCell);
                                }
                            }
                            PdfPCell pdfContainerCell=new PdfPCell(childTable);
                            pdfContainerCell.setBorder(Rectangle.NO_BORDER);
                            table.addCell(pdfContainerCell);
                        }
                        if(ps<columnCount){
                            int left=columnCount-ps;
                            for(int i=0;i<left;i++){
                                PdfPCell pdfMarginCell=new PdfPCell();
                                pdfMarginCell.setBorder(Rectangle.NO_BORDER);
                                table.addCell(pdfMarginCell);
                                pdfMarginCell=new PdfPCell();
                                pdfMarginCell.setBorder(Rectangle.NO_BORDER);
                                table.addCell(pdfMarginCell);
                            }
                        }
                        // 加入文字水印
                        Object watermark = report.getContext().getParameters().get("watermark");
                        writer.setPageEvent(new Watermark(watermark));
                        // 加入图片水印
                        writer.setPageEvent(new ImageWatermark());
                        document.add(table);
                        document.newPage();
                    }
                    
                }else{
                    List<Page> pages=report.getPages();
                    Map<Row, Map<Column, Cell>> cellMap=report.getRowColCellMap();
                    for(Page page:pages){
                        PdfPTable table=new PdfPTable(colSize);
                        table.setLockedWidth(true);
                        table.setTotalWidth(totalWidth);
                        table.setWidths(columnsWidth);
                        table.setHorizontalAlignment(Element.ALIGN_LEFT);
                        List<Row> rows=page.getRows();
                        for(Row row:rows){
                            Map<Column,Cell> colMap=cellMap.get(row);
                            if(colMap==null){
                                continue;
                            }
                            for(Column col:columns){
                                if(col.getWidth()<1){
                                    continue;
                                }
                                Cell cell=colMap.get(col);
                                if(cell==null){
                                    continue;
                                }
                                int cellHeight=buildCellHeight(cell,rows);
                                PdfPCell pdfcell=buildPdfPCell(cell,cellHeight);
                                table.addCell(pdfcell);
                            }
                        }
                        // 加入文字水印
                        Object watermark = report.getContext().getParameters().get("watermark");
                        writer.setPageEvent(new Watermark(watermark));
                        // 加入图片水印
                        writer.setPageEvent(new ImageWatermark());
                        document.add(table);
                        document.newPage();
                    }
                }
                document.close();
            }catch(Exception ex){
                throw new ReportComputeException(ex);
            }
        }
    
        
        private int buildCellHeight(Cell cell,List<Row> rows){
            int height=cell.getRow().getRealHeight();
            int rowSpan=cell.getPageRowSpan();
            if(rowSpan>0){
                int pos=rows.indexOf(cell.getRow());
                int start=pos+1,end=start+rowSpan-1;
                for(int i=start;i<end;i++){
                    height+=rows.get(i).getRealHeight();
                }
            }
            return height;
        }
        
        private PdfPCell buildPdfPCell(Cell cellInfo,int cellHeight) throws Exception{
            CellStyle style=cellInfo.getCellStyle(); 
            CellStyle customStyle=cellInfo.getCustomCellStyle();
            CellStyle rowStyle=cellInfo.getRow().getCustomCellStyle();
            CellStyle colStyle=cellInfo.getColumn().getCustomCellStyle();
            PdfPCell cell=newPdfCell(cellInfo,cellHeight);
            cell.setPadding(0);
            cell.setBorder(PdfPCell.NO_BORDER);
            cell.setCellEvent(new CellBorderEvent(style,customStyle));
            int rowSpan=cellInfo.getPageRowSpan();
            if(rowSpan>0){
                cell.setRowspan(rowSpan);
            }
            int colSpan=cellInfo.getColSpan();
            if(colSpan>0){
                cell.setColspan(colSpan);
            }
            Alignment align=style.getAlign();
            if(customStyle!=null && customStyle.getAlign()!=null){
                align=customStyle.getAlign();
            }
            if(rowStyle!=null && rowStyle.getAlign()!=null){
                align=rowStyle.getAlign();
            }
            if(colStyle!=null && colStyle.getAlign()!=null){
                align=colStyle.getAlign();
            }
            if(align!=null){
                if(align.equals(Alignment.left)){
                    cell.setHorizontalAlignment(Element.ALIGN_LEFT);
                }else if(align.equals(Alignment.center)){
                    cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                }else if(align.equals(Alignment.right)){
                    cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
                }
            }
            Alignment valign=style.getValign();
            if(customStyle!=null && customStyle.getValign()!=null){
                valign=customStyle.getValign();
            }
            if(rowStyle!=null && rowStyle.getValign()!=null){
                valign=rowStyle.getValign();
            }
            if(colStyle!=null && colStyle.getValign()!=null){
                valign=colStyle.getValign();
            }
            if(valign!=null){
                if(valign.equals(Alignment.top)){
                    cell.setVerticalAlignment(Element.ALIGN_TOP);
                }else if(valign.equals(Alignment.middle)){
                    cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
                }else if(valign.equals(Alignment.bottom)){
                    cell.setVerticalAlignment(Element.ALIGN_BOTTOM);
                }
            }
            String bgcolor=style.getBgcolor();
            if(customStyle!=null && StringUtils.isNotBlank(customStyle.getBgcolor())){
                bgcolor=customStyle.getBgcolor();
            }
            if(rowStyle!=null && StringUtils.isNotBlank(rowStyle.getBgcolor())){
                bgcolor=rowStyle.getBgcolor();
            }
            if(colStyle!=null && StringUtils.isNotBlank(colStyle.getBgcolor())){
                bgcolor=colStyle.getBgcolor();
            }
            if(StringUtils.isNotEmpty(bgcolor)){
                String[] colors=bgcolor.split(",");
                cell.setBackgroundColor(new BaseColor(Integer.valueOf(colors[0]),Integer.valueOf(colors[1]),Integer.valueOf(colors[2])));
            }
            return cell;
        }
        
        private int[] buildColumnSizeAndTotalWidth(List<Column> columns,List<Integer> list){
            int count=0,totalWidth=0;
            for(int i=0;i<columns.size();i++){
                Column col=columns.get(i);
                int width=col.getWidth();
                if(width<1){
                    continue;
                }
                count++;
                list.add(width);
                totalWidth+=width;
            }
            return new int[]{count,totalWidth};
        }
        
        private PdfPCell newPdfCell(Cell cellInfo,int cellHeight) throws Exception{
            PdfPCell cell=null;
            Object cellData=cellInfo.getFormatData();
            if(cellData instanceof Image){
                Image img=(Image)cellData;
                cell=new PdfPCell(buildPdfImage(img.getBase64Data(), 0, 0));
            }else if(cellData instanceof ChartData){
                ChartData chartData=(ChartData)cellData;
                String base64Data=chartData.retriveBase64Data();
                if(base64Data!=null){
                    Image img=new Image(base64Data,chartData.getWidth(),chartData.getHeight());
                    cell=new PdfPCell(buildPdfImage(img.getBase64Data(), 0, 0));
                }else{
                    cell=new PdfPCell();
                    CellPhrase pargraph=new CellPhrase(cellInfo,"");
                    cell.setPhrase(pargraph);
                    cell.setFixedHeight(cellHeight);
                }
            }else{
                cell=new PdfPCell();
                CellPhrase pargraph=new CellPhrase(cellInfo,cellData);
                cell.setPhrase(pargraph);
                cell.setFixedHeight(cellHeight);
            }
            CellStyle style=cellInfo.getCellStyle();
            if(style!=null && style.getLineHeight()>0){
                cell.setLeading(style.getLineHeight(), style.getLineHeight());          
            }
            return cell;
        }
        private com.itextpdf.text.Image buildPdfImage(String base64Data, int width,int height) throws Exception{
            com.itextpdf.text.Image pdfImg=null;
            InputStream input=ImageUtils.base64DataToInputStream(base64Data);
            try{
                byte[] bytes=IOUtils.toByteArray(input);
                pdfImg=com.itextpdf.text.Image.getInstance(bytes);
                float imgWidth=pdfImg.getWidth();
                float imgHeight=pdfImg.getHeight();
                if(width==0){
                    width=Float.valueOf(imgWidth).intValue();
                }
                if(height==0){
                    height=Float.valueOf(imgHeight).intValue();
                }
                width=UnitUtils.pixelToPoint(width-2);
                height=UnitUtils.pixelToPoint(height-2);
                pdfImg.scaleToFit(width,height);
            }finally{
                IOUtils.closeQuietly(input);
            }
            return pdfImg;
        }
    }
    
    

    说明: 源码就添加了一行

    2.2 编写文字水印实现类继承PdfPageEventHelper

    package com.bstek.ureport.export.pdf;
    
    import com.itextpdf.text.Document;
    import com.itextpdf.text.Element;
    import com.itextpdf.text.Font;
    import com.itextpdf.text.Phrase;
    import com.itextpdf.text.pdf.ColumnText;
    import com.itextpdf.text.pdf.GrayColor;
    import com.itextpdf.text.pdf.PdfPageEventHelper;
    import com.itextpdf.text.pdf.PdfWriter;
    
    public class Watermark extends PdfPageEventHelper {
    
        Font FONT = new Font(Font.FontFamily.HELVETICA, 50, Font.BOLD, BaseColor.RED);
        private String waterCont;//水印内容
        public Watermark() {
    
        }
        public Watermark(Object waterCont) {
            if (null != waterCont) {
                this.waterCont = waterCont.toString();
            }
        }
    
        @Override
        public void onEndPage(PdfWriter writer, Document document) {
            PdfContentByte pdfContentByte = writer.getDirectContentUnder();
            // 设置水印透明度
            PdfGState gs = new PdfGState();
            // 设置填充字体不透明度为0.2f
            gs.setFillOpacity(0.2f);
            pdfContentByte.setGState(gs);
            for(int i=0 ; i<5; i++) {
                for(int j=0; j<5; j++) {
                    ColumnText.showTextAligned(pdfContentByte,
                            Element.ALIGN_CENTER,
                            new Phrase(this.waterCont == null ? "HELLO" : this.waterCont, FONT),
                            (60.5f+i*250),
                            (40.0f+j*150),
                            writer.getPageNumber() % 2 == 1 ? 45 : -45);
                }
            }
        }
    }
    
    

    2.3 编写图片水印实现类继承PdfPageEventHelper

    package com.bstek.ureport.export.pdf;
    
    import com.itextpdf.text.Document;
    import com.itextpdf.text.Element;
    import com.itextpdf.text.Font;
    import com.itextpdf.text.Phrase;
    import com.itextpdf.text.pdf.ColumnText;
    import com.itextpdf.text.pdf.GrayColor;
    import com.itextpdf.text.pdf.PdfPageEventHelper;
    import com.itextpdf.text.pdf.PdfWriter;
    
    public class ImageWatermark extends PdfPageEventHelper {
        public ImageWatermark () {
    
        }
        public ImageWatermark (Object waterCont) {
            if (null != waterCont) {
                this.waterCont = waterCont.toString();
            }
        }
    
        @Override
        public void onEndPage(PdfWriter writer, Document document) {
            PdfContentByte pdfContentByte = writer.getDirectContentUnder();
            // 设置水印透明度
            PdfGState gs = new PdfGState();
            // 设置填充字体不透明度为0.3f
            gs.setFillOpacity(0.5f);
            pdfContentByte.setGState(gs);
    
            try {
                // 获取图片
                InputStream inputStream = this.getClass().getResourceAsStream("/image/水印.png");
                byte[] bytes = toByteArray(inputStream);
                com.itextpdf.text.Image img = com.itextpdf.text.Image.getInstance(bytes);// 插入水印
                //设置图片水印的位置。
                img.setAbsolutePosition(0, 0);
                img.scaleToFit(864,612);
                pdfContentByte.addImage(img);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (DocumentException e) {
                e.printStackTrace();
            }
        }
        // 输入流转字节数组
        public byte[] toByteArray(InputStream input) throws IOException {
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024*4];
            int n = 0;
            while (-1 != (n = input.read(buffer))) {
                output.write(buffer, 0, n);
            }
            return output.toByteArray();
        }
    }
    
    

    2.3 测试

    三. 不覆盖源码

    如果不覆盖源码加水印, 那就要新增一套导出逻辑, 只需要模仿原逻辑, 加一种导出的方法就行

    3.1 增加访问入口

    • 继承类: com.bstek.ureport.console.pdf.ExportPdfServletAction
    • 新增一个url入口


    3.2 加一个生成pdf处理逻辑


    com.bstek.ureport.console.pdf.ExportPdfServletAction#buildPdf中可以看到com.bstek.ureport.export.ExportManager#exportPdf是生成pdf的逻辑, 所以要重写这个逻辑

    • 继承类com.bstek.ureport.export.ExportManagerImpl, 模仿com.bstek.ureport.export.ExportManagerImpl#exportPdf重写一个方法exportPdf
    • 继承com.bstek.ureport.export.pdf.PdfProducer模仿com.midea.cloud.ureport.extension.ExtPdfProducer#produce重写方法produce

    相关文章

      网友评论

        本文标题:UReport导出PDF添加文字水印和图片水印

        本文链接:https://www.haomeiwen.com/subject/hkzsektx.html