参考链接
- windows pandoc下载安装
- windows MiKTeX下载
- docker alpine linux 镜像(docker.1ms.run/pandoc/latex:3.8.3-alpine)
- 其他工具 wkhtmltopdf(下载链接)
- alpine安装中文字体
- alpine 安装 apk add font-noto-cjk
- alpine 安装 tlmgr install xecjk
- 简单使用
过程中的错误
- htmlTodocx_test.go:17: 转换失败:pandoc执行失败:exit status 47,错误信息:pdflatex not found. Please select a different --pdf-engine or install pdflatex
--- FAIL: TestHtmlToDocx (0.25s)
下载参考链接中的MiKTeX即可。 - LaTeX Error: File `xeCJK.sty' not found.
go
pandoc test.html -o test.pdf --pdf-engine=xelatex -V mainfont="Noto Serif CJK SC" -V CJKmainfont="Noto Serif CJK SC" -V geometry:margin=1in
Error producing PDF.
! LaTeX Error: File `xeCJK.sty' not found.
Type X to quit or <RETURN> to proceed,
or enter new name. (Default extension: sty)
Enter file name:
! Emergency stop.
<read *>
下载参考链接中的 tlmgr install xecjk(当时alpine linux环境时)
相关代码(go)
html转docx或pdf(入参html文件、docx或者pdf文件)
markdown转docx或pdf(入参markdown字符串、docx或者pdf文件)
go
func NewConvertToFileService(
service *Service,
) *ConvertToFileService {
return &ConvertToFileService{
Service: service,
}
}
type ConvertToFileService struct {
*Service
}
func (s *ConvertToFileService) HtmlToDocx(ctx context.Context, inputFile string, outputFile string) ([]byte, error) {
// 2. 调用Pandoc命令:pandoc input.html -o output.docx
cmd := exec.Command(
"pandoc",
inputFile,
"-o", outputFile,
"--standalone", // 生成独立文档(含头部/样式)
)
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("pandoc执行失败:%v,错误信息:%s", err, stderr.String())
}
// 3. 读取转换后的文件内容
outputBytes, err := os.ReadFile(outputFile)
if err != nil {
return nil, fmt.Errorf("读取输出文件失败:%v", err)
}
return outputBytes, nil
}
func (s *ConvertToFileService) HtmlToPDF(ctx context.Context, inputFile string, outputFile string) ([]byte, error) {
// 1. 构造Pandoc核心参数(直接指定HTML文件作为输入源)
pandocArgs := []string{
inputFile, // 输入源:本地HTML文件路径(替代stdin)
"-o", outputFile,
"--pdf-engine=xelatex", // 指定PDF引擎(解决中文乱码)
"-V", `mainfont=Noto Serif CJK SC`, // 中文主字体(Windows)
"-V", `CJKmainfont=Noto Serif CJK SC`, // 中文主字体(Windows)
"-V", "geometry:margin=1in", // 页面边距:1英寸
}
// 2. 配置中文字体(关键)
//pandocArgs = append(pandocArgs, , fmt.Sprintf("mainfont=%s", "Noto Serif CJK SC"))
// 4. 启动Pandoc进程
cmd := exec.Command("pandoc", pandocArgs...)
s.logger.Warn("执行终端命令:", zap.Any("cmd", cmd.Args))
// 5. 捕获输出(字节流)和错误(无需再写入stdin,因为输入是文件)
var outputBuf bytes.Buffer // 存储PDF字节流(outputPath为空时)
var stderrBuf bytes.Buffer // 存储错误信息
cmd.Stderr = &stderrBuf
// 6. 执行命令
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf(
"pandoc执行失败: %v, 错误详情: %s",
err, strings.TrimSpace(stderrBuf.String()),
)
}
// 7. 返回PDF字节流(若未指定输出文件)
return outputBuf.Bytes(), nil
}
func (s *ConvertToFileService) MdToDOCX(ctx context.Context, inputFile string, outputPath string) ([]byte, error) {
// 1. 构造Pandoc核心参数
pandocArgs := []string{
"-f", "markdown", // 输入格式:Markdown(默认支持GFM)
"-t", "docx", // 输出格式:DOCX
"--standalone", // 生成独立DOCX(含完整结构)
}
// 2. 追加自定义参数(如样式、标题等)
// pandocArgs = append(pandocArgs, extraArgs...)
// 3. 指定输出文件(可选,为空则输出到stdout)
if outputPath != "" {
pandocArgs = append(pandocArgs, "-o", outputPath)
}
// 4. 启动Pandoc进程
cmd := exec.Command("pandoc", pandocArgs...)
// 5. 将Markdown字符串写入Pandoc的标准输入
cmd.Stdin = strings.NewReader(inputFile)
// 6. 捕获输出(字节流)和错误
var outputBuf bytes.Buffer // 存储DOCX字节流(outputPath为空时)
var stderrBuf bytes.Buffer // 存储错误信息
if outputPath == "" {
cmd.Stdout = &outputBuf // 无输出文件时,将DOCX写入stdout
}
cmd.Stderr = &stderrBuf
// 7. 执行命令
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf(
"pandoc执行失败: %v, 错误详情: %s",
err, strings.TrimSpace(stderrBuf.String()),
)
}
// 8. 返回DOCX字节流(若未指定输出文件)
return outputBuf.Bytes(), nil
}
func (s *ConvertToFileService) MDToPDF(ctx context.Context, mdContent, outputPath string) ([]byte, error) {
// 基础参数(固定)
baseArgs := []string{
"-f", "markdown", // 输入格式:Markdown(支持GFM)
"-t", "pdf", // 输出格式:PDF
"-o", outputPath,
"--pdf-engine=xelatex", // 中文兼容核心引擎
"-V", `mainfont=Noto Serif CJK SC`,
"-V", `CJKmainfont=Noto Serif CJK SC`,
"-V", "geometry:margin=1in",
/* "-o", outputPath,
"--pdf-engine=xelatex", // 指定PDF引擎(解决中文乱码)
"-V", `mainfont=Noto Serif CJK SC`, // 中文主字体(Windows)
"-V", `CJKmainfont=Noto Serif CJK SC`, // 中文主字体(Windows)
"-V", "geometry:margin=1in", // 页面边距:1英寸
"-f", "markdown", // 输入格式:Markdown(支持GFM)*/
}
// 启动Pandoc进程
cmd := exec.Command("pandoc", baseArgs...)
// 将Markdown字符串写入Pandoc标准输入
cmd.Stdin = strings.NewReader(mdContent)
// 捕获输出和错误
var outputBuf, stderrBuf bytes.Buffer
if outputPath == "" {
cmd.Stdout = &outputBuf // 无文件时,PDF字节流写入stdout
}
cmd.Stderr = &stderrBuf
s.logger.Warn("执行终端命令:", zap.Any("cmd", cmd.Args))
// 执行命令
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("pandoc执行失败: %v, 错误详情: %s", err, strings.TrimSpace(stderrBuf.String()))
}
return outputBuf.Bytes(), nil
}
使用指令
- html转pdf
go
pandoc test.html -o test.pdf --pdf-engine=xelatex -V mainfont=SimSun -V CJKmainfont=SimSun -V geometry:margin=1in
- docx转pdf
go
pandoc input.docx -o input.pdf --pdf-engine=xelatex -V mainfont="Noto Serif CJK SC" -V CJKmainfont="Noto Serif CJK SC" -V geometry:margin=1in