文档导出为 Word

简要描述

用户使用账号密码登录管理系统并获取 token,使用 token 便可以拿到用户信息

请求 URL

请求方式

  • POST

请求示例

{
  "menuId": "12",
  "html": "<h1>title</h1>"
}

请求参数

参数名类型必选说明
menuIdstring文档菜单id
htmlstring文档 html

返回示例

二进制流

返回参数

二进制流

文档导出为 PDF

简要描述

用户使用账号密码登录管理系统并获取 token,使用 token 便可以拿到用户信息

请求 URL

请求方式

  • POST

请求示例

{
  "menuId": "12",
  "html": "<h1>title</h1>"
}

请求参数

参数名类型必选说明
menuIdstring文档菜单id
htmlstring文档 html

返回示例

二进制流

返回参数

补充

文档支持导出为 Word 和 PDF

  1. 下面是用到的依赖及版本
<!-- itext7html转pdf  -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>html2pdf</artifactId>
    <version>5.0.3</version>
</dependency>

<!-- 中文字体支持 -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>font-asian</artifactId>
    <version>8.0.3</version>
</dependency>

<!-- html 转 word -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.2</version>
</dependency>

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.2</version>
</dependency>

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml-schemas</artifactId>
    <version>4.1.2</version>
</dependency>
  1. Controller 处理请求
@PostMapping("/word")
public void exportWord(HttpServletRequest request, HttpServletResponse response, @RequestBody @Valid IdeaReportDTO reportDTO) throws Exception {
    ideaDocExportService.exportWord(request, response, reportDTO);
}

@PostMapping("/pdf")
public void exportPdf(HttpServletRequest request, HttpServletResponse response, @RequestBody @Valid IdeaReportDTO reportDTO) throws Exception {
    ideaDocExportService.exportPdf(request, response, reportDTO);
}
  1. 导出 Word
/**
 * @param request
 * @param response
 * @param content  富文本内容(html)
 * @param fileName 生成word文件
 * @throws Exception
 */
private static void exportWord(HttpServletRequest request, HttpServletResponse response, String content, String fileName) throws Exception {
    ByteArrayInputStream byteArrayInputStream = null;
    POIFSFileSystem poifsFileSystem = null;
    ServletOutputStream servletOutputStream = null;
    try {
        byte b[] = content.getBytes("GBK"); //这里是必须要设置编码的,不然导出中文就会乱码。
        byteArrayInputStream = new ByteArrayInputStream(b);//将字节数组包装到流中
        poifsFileSystem = new POIFSFileSystem();
        DirectoryEntry directory = poifsFileSystem.getRoot();
        directory.createDocument("WordDocument", byteArrayInputStream); //该步骤不可省略,否则会出现乱码。
        //输出文件
        request.setCharacterEncoding("utf-8");
        response.setContentType("application/msword");//导出word格式
        response.addHeader("Content-Disposition", "attachment;filename=" + fileName + ".doc");
        servletOutputStream = response.getOutputStream();
        poifsFileSystem.writeFilesystem(servletOutputStream);
    } catch (Exception e) {
        log.error("exportWord 生成word出错:",e);
        resetResponse(response, e);
    } finally {
        byteArrayInputStream.close();
        servletOutputStream.close();
        poifsFileSystem.close();
    }
}

private static void resetResponse(HttpServletResponse response, Exception exception)throws IOException {
    // 重置response
    response.reset();
    response.setContentType("application/json");
    response.setCharacterEncoding("utf-8");
    String result = "下载文件失败," + exception.getMessage();
    response.getWriter().println(result);
}
  1. 导出 PDF
private static void exportPDF(HttpServletRequest request, HttpServletResponse response, String content, String fileName) throws IOException {
    try{
        //输出文件
        request.setCharacterEncoding("utf-8");
        response.setContentType("application/pdf");
        response.setCharacterEncoding("utf-8");
        String encodeFileName = URLEncoder.encode(fileName, "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + encodeFileName);
        InputStream stringStream = HtmlToPdfUtils.getStringStream(content);
        HtmlToPdfUtils.convertToPdf(stringStream, "OpenByteCode", null, response.getOutputStream());
    } catch (Exception e) {
        log.error("exportPdf生成pdf出错:",e);
        resetResponse(response, e);
    }

}
/**
 * Itext7转换工具类
 */
@Slf4j
public class HtmlToPdfUtils {

    /**
     * html转pdf
     *
     * @param inputStream  输入流
     * @param waterMark    水印
     * @param fontPath     字体路径,ttc后缀的字体需要添加<b>,0<b/>
     * @param outputStream 输出流
     * @date : 2021/1/15 14:07
     */
    public static void convertToPdf(InputStream inputStream, String waterMark, String fontPath, OutputStream outputStream) throws IOException {

        PdfWriter pdfWriter = new PdfWriter(outputStream);
        PdfDocument pdfDocument = new PdfDocument(pdfWriter);
        //设置为A4大小
        pdfDocument.setDefaultPageSize(PageSize.A4);
        //添加水印
        pdfDocument.addEventHandler(PdfDocumentEvent.END_PAGE, new WaterMarkEventHandler(waterMark));
        //添加分页器,但是目前分页器有点问题,总页数计算有问题
        //pdfDocument.addEventHandler(PdfDocumentEvent.END_PAGE, new PageEventHandler());

        //添加中文字体支持
        ConverterProperties properties = new ConverterProperties();
        FontProvider fontProvider = new FontProvider();

        //设置字体
        PdfFont sysFont = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H");
        fontProvider.addFont(sysFont.getFontProgram(), "UniGB-UCS2-H");

        //添加自定义字体,例如微软雅黑
        if (StringUtils.isNotBlank(fontPath)) {
            PdfFont microsoft = PdfFontFactory.createFont(fontPath, PdfEncodings.IDENTITY_H);
            fontProvider.addFont(microsoft.getFontProgram(), PdfEncodings.IDENTITY_H);
        }

        properties.setFontProvider(fontProvider);

        HtmlConverter.convertToPdf(inputStream, pdfDocument, properties);
        pdfWriter.close();
        pdfDocument.close();
    }



    /**
     * 将一个字符串转化为输入流
     * @param sInputString 字符串
     * @return
     */
    public static InputStream getStringStream(String sInputString) {
        if (sInputString != null && !sInputString.trim().equals("")) {
            try {
                ByteArrayInputStream tInputStringStream = new ByteArrayInputStream(sInputString.getBytes());
                return tInputStringStream;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

}

生成的 PDF 支持水印功能

/**
 * 水印
 */
public class WaterMarkEventHandler implements IEventHandler {

    /**
     * 水印内容
     */
    private String waterMarkContent;

    /**
     * 一页中有几列水印
     */
    private int waterMarkX;

    /**
     * 一页中每列有多少水印
     */
    private int waterMarkY;

    public WaterMarkEventHandler(String waterMarkContent) {
        this(waterMarkContent, 5, 5);
    }

    public WaterMarkEventHandler(String waterMarkContent, int waterMarkX, int waterMarkY) {
        this.waterMarkContent = waterMarkContent;
        this.waterMarkX = waterMarkX;
        this.waterMarkY = waterMarkY;
    }

    @Override
    public void handleEvent(Event event) {

        PdfDocumentEvent documentEvent = (PdfDocumentEvent) event;
        PdfDocument document = documentEvent.getDocument();
        PdfPage page = documentEvent.getPage();
        Rectangle pageSize = page.getPageSize();

        PdfFont pdfFont = null;
        try {
            pdfFont = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H");
        } catch (IOException e) {
            e.printStackTrace();
        }

        PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), document);

        Paragraph waterMark = new Paragraph(waterMarkContent).setOpacity(0.5f);
        Canvas canvas = new Canvas(pdfCanvas, pageSize)
                .setFontColor(WebColors.getRGBColor("lightgray"))
                .setFontSize(16)
                .setFont(pdfFont);

        for (int i = 0; i < waterMarkX; i++) {
            for (int j = 0; j < waterMarkY; j++) {
                canvas.showTextAligned(waterMark, (150 + i * 300), (160 + j * 150), document.getNumberOfPages(), TextAlignment.CENTER, VerticalAlignment.BOTTOM, 120);
            }
        }
        canvas.close();
    }
}