JAVA-PDF文件下载

目录

1.POM依赖

2.测试用的实体类

3.二维码与条形码工具类

4.PDF模板构建

5.Rest层测试


1.POM依赖

        <!--PDF工具-->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.9</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>html2pdf</artifactId>
            <version>2.1.4</version>
        </dependency>
        <dependency>
            <groupId>com.jfinal</groupId>
            <artifactId>jfinal</artifactId>
            <version>3.3</version>
        </dependency>


        <!--二维码与条形码工具-->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.4.1</version>
        </dependency>

2.测试用的实体类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BillDto {

    /**
     * 序号
     */
    private String serialNum;

    /**
     * 费用项目
     */
    private String feeTypeName;

    /**
     * 单价
     */
    private String price;

    /**
     * 数量
     */
    private String qty;

    /**
     * 小计
     */
    private String amount;

    /**
     * 备注
     */
    private String remark;

}

3.二维码与条形码工具类

import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.oned.Code128Writer;
import com.google.zxing.qrcode.QRCodeWriter;
import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Image;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;


public class QRCodeGenerator {

    /**
     * 获取二维码PDF-Image对象
     *
     * @param text   生成二维码的字符文本
     * @param width  二维码宽度
     * @param height 二维码高度
     */
    public static Image buildQR(String text, int width, int height) throws WriterException, IOException, BadElementException {
        return getImage(generateQRCodeImage(text, width, height));
    }


    /**
     * 获取条形码PDF-Image对象
     *
     * @param text   生成条形码的字符文本
     * @param width  条形码宽度
     * @param height 条形码高度
     */
    public static Image buildBar(String text, int width, int height) throws WriterException, IOException, BadElementException {
        return getImage(generateBarcode(text, width, height));
    }

    /**
     * 获取条形码PDF-Image对象(底部带文本--默认与条码一样的串)
     *
     * @param text   生成条形码的字符文本
     * @param width  条形码宽度
     * @param height 条形码高度
     */
    public static Image buildBarWithText(String text, int width, int height) throws WriterException, IOException, BadElementException {
        return getImage(generateBarcodeWithText(text, width, height, text));
    }

    /**
     * 获取条形码PDF-Image对象(底部带文本--自定义)
     *
     * @param text           生成条形码的字符文本
     * @param width          条形码宽度
     * @param height         条形码高度
     * @param additionalText 条形码底部文本
     */
    public static Image buildBarWithText(String text, int width, int height, String additionalText) throws WriterException, IOException, BadElementException {
        if (StringUtils.isEmpty(additionalText)) {
            additionalText = text;
        }
        return getImage(generateBarcodeWithText(text, width, height, additionalText));
    }

    //生成二维码
    public static BufferedImage generateQRCodeImage(String text, int width, int height) throws WriterException, IOException {
        if (width == 0) {
            width = 200;
        }
        if (height == 0) {
            height = 200;
        }
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height);
        return MatrixToImageWriter.toBufferedImage(bitMatrix);
    }

    //生成条形码
    private static BufferedImage generateBarcode(String text, int width, int height) throws WriterException {
        if (width == 0) {
            width = 400;
        }
        if (height == 0) {
            height = 200;
        }
        Code128Writer barcodeWriter = new Code128Writer();
        BitMatrix bitMatrix = barcodeWriter.encode(text, BarcodeFormat.CODE_128, width, height, null);
        return MatrixToImageWriter.toBufferedImage(bitMatrix);
    }

    //生成条形码并在底部添加附加文本
    private static BufferedImage generateBarcodeWithText(String text, int width, int height, String additionalText) throws WriterException, IOException {
        if (width == 0) {
            width = 200;
        }
        if (height == 0) {
            height = 100;
        }
        // 生成条形码
        BufferedImage barcodeImage = generateBarcode(text, width, height);
        // 创建更高的 BufferedImage,用于容纳条形码和附加文本
        BufferedImage combinedImage = new BufferedImage(width, height + 20, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = combinedImage.createGraphics();
        // 设置整个图像的背景为白色
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, width, height + 20);
        // 将条形码绘制到新的 BufferedImage 中
        g2d.drawImage(barcodeImage, 0, 0, null);
        // 设置字体和颜色
        Font font = new Font("Arial", Font.PLAIN, 15);
        g2d.setFont(font);
        g2d.setColor(Color.BLACK);
        // 计算文本位置
        int textWidth = g2d.getFontMetrics().stringWidth(additionalText);
        int x = (width - textWidth) / 2;
        int y = height + 15; // 在条形码下方留出一定的空白
        // 添加附加文本到图片
        g2d.drawString(additionalText, x, y);
        g2d.dispose();
        return combinedImage;
    }

    //装换文件流的图片对象为PDF图片对象
    public static Image getImage(BufferedImage bufferedImage) throws IOException, BadElementException {
        // 将BufferedImage转换为字节数组
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "png", outputStream);
        byte[] imageBytes = outputStream.toByteArray();

        // 将字节数组转换为iText的Image对象
        return Image.getInstance(imageBytes);
    }

}

4.PDF模板构建

注意:这个模板并非傻瓜包,纯属自定义构建一个表单,然后输出,因此每个不一样的模板都需要独立编写

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.google.zxing.WriterException;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.RectangleReadOnly;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.zeng.demo.uitls.QRCodeGenerator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.YearMonth;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;


@Slf4j
public class PdfGenerator {

    public static BaseFont bfChinese;

    /**
     * 公用字体对象
     */
    static {
        try {
            bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //虚拟方法可以忽略,一般自己构建好入参
    private static List<String> getColNames() {
        List<String> columnNameList = new ArrayList<>();
        columnNameList.add("serialNum");
        columnNameList.add("feeTypeName");
        columnNameList.add("price");
        columnNameList.add("qty");
        columnNameList.add("amount");
        columnNameList.add("remark");
        return columnNameList;
    }

    //虚拟方法可以忽略,一般自己查询完数据再入参
    private static ArrayList<BillDto> queryDataList() {
        ArrayList<BillDto> billDtos = new ArrayList<>();
        BillDto billDto = new BillDto("1", "仓租费", "1000", "1", "1000", "元/月");
        billDtos.add(billDto);
        BillDto billDto2 = new BillDto("2", "卸货费", "1000", "1", "1000", "元/月");
        billDtos.add(billDto2);
        BillDto billDto3 = new BillDto("3", "配送费", "1000", "1", "1000", "元/月");
        billDtos.add(billDto3);
        BillDto billDto4 = new BillDto("4", "退货费", "1000", "1", "1000", "元/月");
        billDtos.add(billDto4);
        BillDto billDto5 = new BillDto("5", "打单费", "1000", "1", "1000", "元/月");
        billDtos.add(billDto5);
        BillDto billDto6 = new BillDto("6", "分拣费", "1000", "1", "1000", "元/月");
        billDtos.add(billDto6);
        return billDtos;
    }

    /**
     * 输出模板(这个方法只是用于方便调试看效果)
     */
    public static void main(String[] args) {
        //文件模板
        Document document = null;
        FileOutputStream outputStream = null;
        try {
            document = new Document(new RectangleReadOnly(842.0F, 595.0F), 50, 50, 50, 50);
            //这里不输出需要替换为stream
            outputStream = new FileOutputStream(String.format("D:\\xxxx\\xxxx\\Desktop\\%s.pdf", "123456"));//输出本地的url地址
            PdfWriter.getInstance(document, outputStream);
            document.open();

            // 构建表单(这里的参数不是固定的,可根据自己的表单内容来决定调整方法参数)
            PdfPTable table = createTable();

            // 添加表格到文档中
            document.add(table);
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        } catch (WriterException e) {
            e.printStackTrace();
        } finally {
            //先关闭文档
            if (document != null) {
                document.close();
            }
            //后关闭流
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException ioException) {
                    log.error("释放流失败:", ioException);
                }
            }
        }
    }


    /**
     * 构建PDF-File对象(一般使用该方法得到文件对象)
     */
    public static File buildPdf(String fileName) {
        //文件模板
        File file = null;
        Document document = null;
        FileOutputStream outputStream = null;
        try {
            file = File.createTempFile(fileName, ".pdf");
            document = new Document(new RectangleReadOnly(842.0F, 595.0F), 50, 50, 50, 50);
            //这里不输出需要替换为stream
            outputStream = new FileOutputStream(file);
            PdfWriter.getInstance(document, outputStream);
            document.open();

            // 构建表单
            PdfPTable table = createTable();

            // 添加表格到文档中
            document.add(table);
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        } catch (WriterException e) {
            e.printStackTrace();
        } finally {
            //先关闭文档
            if (document != null) {
                document.close();
            }
            //后关闭流
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException ioException) {
                    log.error("释放流失败:", ioException);
                }
            }
        }
        return file;
    }

    //TODO 构建表单内容这里
    private static PdfPTable createTable() throws DocumentException, IOException, WriterException {
        //TODO 配置动态值(默认数据库查询得到一些信息,也可以作为入参直接传入)
        //查询明细
        List<String> columnNameList = getColNames();
        List<BillDto> dataList = queryDataList();
        String fileName = "xxx月结账单";
        BigDecimal taxes = new BigDecimal("0.16");
        String supplierName = "xxx有限公司";
        Integer startYear = 2024;
        Integer startMonth = 2;
        Calendar calendar = Calendar.getInstance();
        calendar.set(startYear, startMonth - 1, 1);
        calendar.add(Calendar.MONTH, 1);
        //账单的下一个月的年份
        int nextYear = calendar.get(Calendar.YEAR);
        //账单的下一个月的月份
        int nextMonth = calendar.get(Calendar.MONTH) + 1;
        YearMonth yearMonth = YearMonth.of(nextYear, nextMonth);
        //账单结算的最后一天
        int endDays = yearMonth.lengthOfMonth();
        //不含税总金额
        BigDecimal totalAmount = CollectionUtils.isNotEmpty(dataList) ? dataList.stream().map(e -> new BigDecimal(e.getAmount())).reduce(BigDecimal.ZERO, BigDecimal::add) : BigDecimal.ZERO;
        //税金
        BigDecimal taxesPrice = taxes.multiply(totalAmount);
        String taxesPriceStr = taxesPrice.setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
        //含税总金额
        BigDecimal totalPrice = totalAmount.add(taxesPrice);
        String totalPriceStr = totalPrice.setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
        // 创建表格
        PdfPTable table = new PdfPTable(6);
        table.setWidthPercentage(100);
        //构建空单元格(标准化的单元格,使用全边框)
        PdfPCell Empty = buildEmpty(0);

        //--------------------------------------抬头6列的大标题(开始)--------------------------------------

        //LOGO图片需要切换成项目的相对路径
            /*try {
                //获取指定地址的图片(可以是网络图片地址,也可以是本地的图片地址)
                //Image logo = Image.getInstance("https://www.xxxx.com.png");

                //通过输入流获取resources目录下的相对路径图片文件
                InputStream inputStream = PdfGenerator.class.getClassLoader().getResourceAsStream("picture/anntoLogo.png");
                BufferedImage logoBuffer = ImageIO.read(inputStream);
                Image logo = Image.getInstance(logoBuffer, null);

                //设置图片的参数
                logo.scaleAbsolute(95, 80);//图片尺寸
                logo.scaleToFit(95, 80);//填充图片的尺寸
                logo.setAlignment(Image.RIGHT | Image.ALIGN_TOP);//图片的位置
                PdfPCell logCell = new PdfPCell(logo, false);//构建的图片大小填充选择,false以absolute为准,ture以scaleToFit为准
                logCell.setBorder(PdfPCell.TOP | PdfPCell.BOTTOM | PdfPCell.LEFT);//边框的显示注意要同时指定用|分隔
                logCell.setPaddingTop(0);//图片距离顶部的边距
                logCell.setPaddingLeft(5);//图片距离左侧的边距
                logCell.setPaddingRight(2);//图片距离右侧的边距
                logCell.setPaddingBottom(10);//图片距离底部的边距
                table.addCell(logCell);
            } catch (Exception pe) {
                log.error("logo图片读取失败,已设置为空单元格");
                //没有图片时直接变成空元素,这里由于logo位置在左上角,因此空单元格的边框去上下左即可
                PdfPCell leftEmptyCell = buildEmpty(PdfPCell.TOP | PdfPCell.BOTTOM | PdfPCell.LEFT);
                table.addCell(leftEmptyCell);
            }*/

        //生成二维码
        String QR = "BH2024041600001";
        Image qr = QRCodeGenerator.buildQR(QR, 200, 200);
        qr.scaleAbsolute(50, 50);
        qr.scaleToFit(50, 50);
        qr.setAlignment(Image.RIGHT | Image.ALIGN_TOP);
        PdfPCell logCell = new PdfPCell(qr, true);
        logCell.setBorder(PdfPCell.TOP | PdfPCell.BOTTOM | PdfPCell.LEFT);
        logCell.setPaddingTop(2);
        logCell.setPaddingLeft(2);
        logCell.setPaddingRight(2);
        logCell.setPaddingBottom(30);
        table.addCell(logCell);

        //创建标题
        String topic = "芜湖安得智联科技有限公司" + "\n" + "\n" + "Wuhu  Annto  Logisitics  Technology  Co.,  Ltd.";
        PdfPCell topicCell = buildTopicCell(topic, 15);
        //topicCell.setColspan(4);
        topicCell.setColspan(3);
        topicCell.setBorder(PdfPCell.TOP | PdfPCell.BOTTOM);
        topicCell.setPadding(10);
        table.addCell(topicCell);

        //因为想堆成LOGO的单元格,左右两边各占用一个位
            /*PdfPCell rightEmptyCell = buildEmpty(PdfPCell.TOP | PdfPCell.BOTTOM | PdfPCell.RIGHT);
            table.addCell(rightEmptyCell);*/

        //条形码(取代上面的空单元格为条形码,但此处占用的是2列,上面标题那里Colspan也从4列改成了3列)
        String barcode = "1234567890";
        Image bar = QRCodeGenerator.buildBar(barcode, 500, 150);
        bar.scaleAbsolute(150, 50);
        bar.scaleToFit(150, 50);
        bar.setAlignment(Image.RIGHT | Image.ALIGN_TOP);
        PdfPCell barcodeCell = new PdfPCell(bar, true);
        barcodeCell.setColspan(2);
        barcodeCell.setBorder(PdfPCell.TOP | PdfPCell.BOTTOM | PdfPCell.RIGHT);
        barcodeCell.setPaddingTop(20);
        barcodeCell.setPaddingLeft(2);
        barcodeCell.setPaddingRight(2);
        barcodeCell.setPaddingBottom(20);
        table.addCell(barcodeCell);

        //--------------------------------------抬头6列的大标题(结束)--------------------------------------

        //账单名称
        String billName = String.format("%s年%s月应收款对账单", startYear, startMonth);
        PdfPCell billNameCell = buildTopicCell(billName, 15);
        billNameCell.setColspan(6);
        table.addCell(billNameCell);

        //费用简述
        String billDesc = String.format("%s年%s月%s日前%s应向芜湖安得智联科技有限公司支付%s年%s月份的物流服务费%s元,详见下表:", nextYear, nextMonth, endDays, supplierName, startYear, startMonth, totalPriceStr);
        PdfPCell billDescCell = buildCell(billDesc, 9);
        billDescCell.setColspan(6);
        table.addCell(billDescCell);

        //账单表头
        PdfPCell headerCell1 = buildCell("序号", 9);
        PdfPCell headerCell2 = buildCell("日期/月份", 9);
        PdfPCell headerCell3 = buildCell("费用标准", 9);
        PdfPCell headerCell4 = buildCell("数量", 9);
        PdfPCell headerCell5 = buildCell("小计(单位元)", 9);
        PdfPCell headerCell6 = buildCell("备注", 9);
        table.addCell(headerCell1);
        table.addCell(headerCell2);
        table.addCell(headerCell3);
        table.addCell(headerCell4);
        table.addCell(headerCell5);
        table.addCell(headerCell6);

        //TODO 创建数据行(这里自定义生成的东西)
        if (CollectionUtils.isNotEmpty(dataList)) {
            for (BillDto billDto : dataList) {
                //序列化成Map<String,String>
                Map<String, String> data = JSON.parseObject(JSON.toJSONString(billDto), new TypeReference<Map<String, String>>() {
                });
                for (String columnName : columnNameList) {
                    String dataCol = data.get(columnName);
                    PdfPCell dataCell = buildCell(dataCol);
                    table.addCell(dataCell);
                }
            }
        }

        //税金行
        String taxesSerNum = String.valueOf(dataList.size() + 1);
        PdfPCell taxesSerCell = buildCell(taxesSerNum);
        PdfPCell taxesNameCell = buildCell("税金");
        PdfPCell taxesPriceCell = buildCell(taxesPriceStr);
        table.addCell(taxesSerCell);
        table.addCell(taxesNameCell);
        table.addCell(Empty);
        table.addCell(Empty);
        table.addCell(taxesPriceCell);
        table.addCell(Empty);

        //合计金额行
        PdfPCell totalPriceNameCell = buildCell("合计金额");
        totalPriceNameCell.setColspan(4);
        table.addCell(totalPriceNameCell);
        PdfPCell totalPriceCell = buildCell(totalPriceStr);
        table.addCell(totalPriceCell);
        table.addCell(Empty);

        //落款
        String warning = String.format("烦请贵司于%s年%s月15日前核对后签字盖章回传我司,谢谢合作!", nextYear, nextMonth);
        PdfPCell warningCell = buildLeftCell(warning);
        warningCell.setColspan(4);
        table.addCell(warningCell);
        table.addCell(Empty);
        table.addCell(Empty);

        //委托方
        String supplier = String.format("委托方:%s(盖章)", supplierName);
        PdfPCell supplierCell = buildLeftCell(supplier);
        supplierCell.setColspan(3);
        //承运方
        String factory = String.format("承运方:芜湖安得智联科技有限公司(盖章)");
        PdfPCell factoryCell = buildLeftCell(factory);
        factoryCell.setColspan(3);
        table.addCell(supplierCell);
        table.addCell(factoryCell);

        //地址行
        String addressPre = "地址:";
        String factorAddDetail = "湖北省武汉市蔡甸区千子山大道199号";
        PdfPCell supplierAddCell = buildLeftCell(addressPre);
        supplierAddCell.setColspan(3);
        PdfPCell factorAddCell = buildLeftCell(addressPre + factorAddDetail);
        factorAddCell.setColspan(3);
        table.addCell(supplierAddCell);
        table.addCell(factorAddCell);

        //电话行
        String telPre = "电话:";
        String factorTel = "13657221132";
        PdfPCell supplierTelCell = buildLeftCell(telPre);
        supplierTelCell.setColspan(3);
        PdfPCell factorTelCell = buildLeftCell(telPre + factorTel);
        factorTelCell.setColspan(3);
        table.addCell(supplierTelCell);
        table.addCell(factorTelCell);

        //确认行
        String confirmPre = "确认:";
        PdfPCell confirmCell = buildLeftCell(confirmPre);
        confirmCell.setColspan(3);
        table.addCell(confirmCell);
        table.addCell(confirmCell);

        //日期行
        //电话行
        String datePre = "日期:";
        String nowDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        PdfPCell supplierDateCell = buildLeftCell(datePre);
        supplierDateCell.setColspan(3);
        PdfPCell factorDateCell = buildLeftCell(datePre + nowDate);
        factorDateCell.setColspan(3);
        table.addCell(supplierDateCell);
        table.addCell(factorDateCell);
        return table;
    }

    //构建空单元格(入参0是默认全边框,也可以自定义全边框)
    private static PdfPCell buildEmpty(int borderParam) throws DocumentException, IOException {
        int defaultBorder = PdfPCell.TOP | PdfPCell.BOTTOM | PdfPCell.LEFT | PdfPCell.RIGHT;
        PdfPCell Empty = buildCell("", 15);
        if (borderParam == 0) {
            Empty.setBorder(defaultBorder);
        } else {
            Empty.setBorder(borderParam);
        }
        Empty.setPadding(10);
        return Empty;
    }

    //构建标题单元格(默认加粗,黑色字体)
    private static PdfPCell buildTopicCell(String text, int size) {
        //字体文本格式
        Font fontChinese = new Font(bfChinese, size, Font.BOLD, BaseColor.BLACK);
        PdfPCell cell = new PdfPCell(new Paragraph(text, fontChinese));
        cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
        cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
        cell.setPadding(5);
        return cell;
    }

    //创建正常单元格(字体大小自定义,不加粗,黑色字体)
    private static PdfPCell buildCell(String text, float size) throws DocumentException, IOException {
        //字体文本格式
        Font fontChinese = new Font(bfChinese, size, Font.NORMAL, BaseColor.BLACK);
        PdfPCell cell = new PdfPCell(new Paragraph(text, fontChinese));
        cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
        cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
        cell.setPadding(5);
        return cell;
    }

    //创建默认单元格(字体大小-10,不加粗,黑色字体)
    private static PdfPCell buildCell(String text) throws DocumentException, IOException {
        //字体文本格式
        Font fontChinese = new Font(bfChinese, 10, Font.NORMAL, BaseColor.BLACK);
        PdfPCell cell = new PdfPCell(new Paragraph(text, fontChinese));
        //统一文本与边框的边距
        cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
        cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
        cell.setPadding(5);
        return cell;
    }

    //创建字体靠左的单元格(字体大小-10,不加粗,黑色字体)
    private static PdfPCell buildLeftCell(String text) throws DocumentException, IOException {
        //字体文本格式
        Font fontChinese = new Font(bfChinese, 10, Font.BOLD, BaseColor.BLACK);
        PdfPCell cell = new PdfPCell(new Paragraph(text, fontChinese));
        //统一文本与边框的边距
        cell.setHorizontalAlignment(PdfPCell.ALIGN_LEFT);
        cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
        cell.setPadding(5);
        return cell;
    }

}


5.Rest层测试

import com.zeng.demo.pdf.PdfGenerator;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;


@RestController
public class TestFileDownload {

    /**
     * 通过读取url下载文件
     */
    @GetMapping(value = "/getPdfFile")
    public ResponseEntity<ByteArrayResource> getPdfFile(@RequestParam("url") String url) throws IOException {
        try {
            //优化url处理,有些地址会自带这玩意导致无法正常加载文件
            url = url.replace("\u202A", "");
            File file = new File(url);
            byte[] bytes = toByteArray(file);
            ByteArrayResource resource = new ByteArrayResource(bytes);

            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=output.pdf");

            return ResponseEntity.ok().headers(headers).contentLength(bytes.length).contentType(MediaType.APPLICATION_PDF).body(resource);

        } catch (Exception e) {
            return ResponseEntity.badRequest().build();
        }
    }


    /**
     * 直接输出字节流文件给前端
     */
    @GetMapping(value = "/getPdfFileByLocal")
    public ResponseEntity<ByteArrayResource> getPdfFileByLocal(@RequestParam("name") String name) throws IOException {
        try {
            File file = PdfGenerator.buildPdf(name);
            byte[] bytes = toByteArray(file);
            ByteArrayResource resource = new ByteArrayResource(bytes);

            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=output.pdf");

            return ResponseEntity.ok().headers(headers).contentLength(bytes.length).contentType(MediaType.APPLICATION_PDF).body(resource);

        } catch (Exception e) {
            return ResponseEntity.badRequest().build();
        }
    }


    public static byte[] toByteArray(File file) throws IOException {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            byte[] bytes = new byte[(int) file.length()];
            fis.read(bytes);
            return bytes;
        } finally {
            if (fis != null) {
                fis.close();
            }
        }
    }
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值