• 导入依赖
<!-- pdf-->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.11</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>5.5.11</version>
        </dependency>
  • 编写工具类

PDFUtil :

import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;

/**
 * @Description: pdf工具类
 */
public class PDFUtil {

    /**
     * 生成文字段落
     * @param content 渲染的文字内容
     * @param font 字体
     * @param alignment 设定段落的对齐方式,参数1为居中对齐、2为右对齐、3为左对齐,默认为左对齐。
     * @return 返回文档段落
     */
    public static Paragraph getParagraph (String content, Font font, Integer alignment){
        Paragraph paragraph = new Paragraph(content,font) ;
        if (alignment != null && alignment >= 0){
            paragraph.setAlignment(alignment);
        }
        return paragraph ;
    }

    /**
     * 生成图片段落
     * @param imgPath 图片路径
     * @param width 图片宽度
     * @param height 图片高度
     * @return  返回图片段落
     * @throws Exception
     */
    public static Image getImage (String imgPath, float width, float height) throws Exception {
        Image image = Image.getInstance(imgPath);
        image.setAlignment(Image.MIDDLE);
        if (width > 0 && height > 0){
            image.scaleAbsolute(width, height);
        }
        return image ;
    }

    /**
     * 生成表格段落
     * @param numColumns 表格列数
     * @param totalWidth 表格宽度
     * @return 返回表格段落
     * @throws Exception
     */
    public static PdfPTable getPdfPTable (int numColumns, float totalWidth) throws Exception {
        // 表格处理
        PdfPTable table = new PdfPTable(numColumns);
        // 设置表格宽度比例为%100
        table.setWidthPercentage(100);
        // 设置宽度:宽度平均
        table.setTotalWidth(totalWidth);
        // 锁住宽度
        table.setLockedWidth(true);
        // 设置表格上面空白宽度
        table.setSpacingBefore(10f);
        // 设置表格下面空白宽度
        table.setSpacingAfter(10f);
        // 设置表格默认为无边框
        table.getDefaultCell().setBorder(0);
        table.setPaddingTop(50);
        table.setSplitLate(false);
        return table ;
    }
    /**
     * 表格内容
     */
    public static PdfPCell getPdfPCell (Phrase phrase){
        return new PdfPCell (phrase) ;
    }

    /**
     * 设置表格数据带样式
     * @param dataTable 表格
     * @param font 字体
     * @param cellList 表格数据
     */
    public static void addTableCell (PdfPTable dataTable, Font font, List<String> cellList){
        for (String content:cellList) {
            dataTable.addCell(getParagraph(content,font,-1));
        }
    }

    /**
     * 文件下载
     * @param path
     * @param response
     */
    public static  void downloadNet(String path, HttpServletResponse response) {
        InputStream fis = null;
        OutputStream out = null;
        // path是指欲下载的文件的路径。
        File file = new File(path);
        // 取得文件名。
        String fileName = file.getName();
        System.out.println(fileName);
        try {
            fis = new BufferedInputStream(new FileInputStream(path));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            // 清空response
//            response.reset();
            out = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            //如果输出的是中文名的文件,在此处就要用URLEncoder.encode方法进行处理
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            out.write(buffer);
            out.flush();

        } catch (IOException ex) {
            ex.getStackTrace();
        } finally {
            try {
                File f = new File(path);
                f.delete();
                if (fis != null) {
                    fis.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


}
  • 编写业务类
    CreatePDFService:
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: 创建PDF测试类
 */
public class CreatePDFService {
    /**
     * PDF使用的字体,此处使用的是windos自带的字体
     */
    private static String FONT = "C:\\Windows\\Fonts\\Simhei.ttf";

    private static String PAGE_TITLE = "汽车租赁合同" ;

    /**
     * pdf标题样式
     */
    private static Font TITLE_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H,20, Font.BOLD);
    /**
     * 标签样式,等同于 <h1>
     */
    private static Font NODE_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H,15, Font.BOLD);
    /**
     * 标签样式,等同于 <h2>
     */
    private static Font BLOCK_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H,13, Font.BOLD, BaseColor.BLACK);
    /**
     * 内容样式
     */
    private static Font INFO_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H,12, Font.NORMAL,BaseColor.BLACK);
    /**
     * 表格文字样式
     */
    private static Font CONTENT_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);


    /**
     * 创建pdf
     * @return
     * @throws Exception
     */
    public static String createPdfPage () throws Exception {
        File path = new File(System.getProperty("java.io.tmpdir") + File.separator + "pdf");
        if (path.mkdirs()) ;

        String outPdfPath = path + File.separator + "测试.pdf";

        // 创建文档
        Document document = new Document();
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outPdfPath));
        document.open();
        // 报告标题
        document.add(PDFUtil.getParagraph(PAGE_TITLE,TITLE_FONT,1)) ;
        document.add(PDFUtil.getParagraph("\n租赁人:张三",INFO_FONT,-1)) ;
        document.add(PDFUtil.getParagraph("\n出租方:好车车汽车租赁有限公司\n\n",INFO_FONT,-1)) ;
        // 报告内容
        // 段落标题 + 报表图
        document.add(PDFUtil.getParagraph("城市数据分布统计",NODE_FONT,-1)) ;
        document.add(PDFUtil.getParagraph("\n· 可视化图表\n\n",BLOCK_FONT,-1)) ;
        // 设置图片宽高
        float documentWidth = document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin();
        float documentHeight = documentWidth / 580 * 320;
        document.add(PDFUtil.getImage("D:\\chat\\a.png",documentWidth-80,documentHeight-80)) ;
        // 数据表格
        document.add(PDFUtil.getParagraph("\n· 数据详情\n\n",BLOCK_FONT,-1)) ;
        PdfPTable dataTable = PDFUtil.getPdfPTable(6,500) ;
        // 设置表格
        List<String> tableHeadList = tableHead () ;
        List<List<String>> tableDataList = getTableData () ;
        PDFUtil.addTableCell(dataTable,CONTENT_FONT,tableHeadList);
        for (List<String> tableData : tableDataList) {
            PDFUtil.addTableCell(dataTable,CONTENT_FONT,tableData);
        }
        document.add(dataTable);
        document.add(PDFUtil.getParagraph("\n· 报表描述\n\n",BLOCK_FONT,-1)) ;
        document.add(PDFUtil.getParagraph("数据报告可以监控每天的推广情况," +
                "可以针对不同的数据表现进行分析,以提升推广效果。",CONTENT_FONT,-1)) ;
        document.newPage() ;
        document.close();
        writer.close();

        return outPdfPath;

    }

    /**
     * 生成表格数据
     * @return
     */
    public static List<List<String>> getTableData (){
        List<List<String>> tableDataList = new ArrayList<>() ;
        for (int i = 0 ; i < 3 ; i++){
            List<String> tableData = new ArrayList<>() ;
            tableData.add("浙江"+i) ;
            tableData.add("杭州"+i) ;
            tableData.add("276"+i) ;
            tableData.add("33.3%") ;
            tableData.add("33.3%") ;
            tableData.add("33.3%") ;
            tableData.add("33.3%") ;
            tableData.add("33.3%") ;
            tableDataList.add(tableData) ;
        }
        return tableDataList ;
    }

    /**
     * 创建表格标题
     * @return
     */
    public static List<String> tableHead (){
        List<String> tableHeadList = new ArrayList<>() ;
        tableHeadList.add("省份") ;
        tableHeadList.add("城市") ;
        tableHeadList.add("数量") ;
        tableHeadList.add("百分比") ;
        tableHeadList.add("百分比") ;
        tableHeadList.add("百分比") ;
        tableHeadList.add("百分比2") ;
        tableHeadList.add("百分比1") ;
        return tableHeadList ;
    }

}

注:以上文件地址,及图片地址需要替换为自己的目录

  • 编写接口

TestController :

import com.example.demo.util.CreatePDFService;
import com.example.demo.util.PDFUtil;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.*;


@RestController
@RequestMapping("/api")
public class TestController {

    /**
     * 导出PDF
     * @param response
     * @throws FileNotFoundException
     */
    @PostMapping("/exportPdf")
    public void  goetPdf(HttpServletResponse response) throws FileNotFoundException {
        String path = null;
        try {
            path = CreatePDFService.createPdfPage();
        } catch (Exception e) {
            e.printStackTrace();
        }
        PDFUtil.downloadNet(path, response);

    }
}
  • Vue调用接口及接收文件流
export default {
    data() {
      return {
      }
    },
    methods: {
      //导出pdf文件,此处的exportPdf是请求接口/api/exportPdf的方法,此处直接替换为axios代码请求即可
      //后端返回的是文件流
      exportPdf(orderParam).then(res => {
        if (res) {
          let fileName= "测试"
          this.downloadFile(res,fileName, "pdf");
        }
      });
    },
    //下载pdf
    downloadFile(obj, name, suffix) {
      const url = window.URL.createObjectURL(new Blob([obj]))
      const link = document.createElement('a')
      link.style.display = 'none'
      link.href = url
      // const fileName = parseTime(new Date()) + '-' + name + '.' + suffix
      const fileName = name + '.' + suffix;
      link.setAttribute('download', fileName)
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    },


  },
  • 请求结果
    响应文件流
  • PDF下载效果