pandoc安装与使用(html、makdown转docx、pdf)

参考链接

过程中的错误

  • 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
相关推荐
无心使然11 小时前
Openlayers调用ArcGis要素服务之一 ——要素查询 (/query)
前端·javascript·数据可视化
ZC跨境爬虫11 小时前
跟着 MDN 学 HTML day_1:(全套原生Input+表单结构拆解)
前端·css·ui·html
焰火199911 小时前
[前端]单文件上传组件
前端·vue.js
kyriewen1111 小时前
Next.js部署:从本地跑得欢,到线上飞得稳
开发语言·前端·javascript·科技·react.js·前端框架·ecmascript
慕容卡卡11 小时前
Claude 使用神器(web页面)--CloudCLI UI
java·开发语言·前端·人工智能·ui·spring cloud
JarvanMo11 小时前
搞懂这 5 个 AI 术语,你就超过了 90% 的人
前端·后端
IT_陈寒11 小时前
Vite的HMR怎么突然失效了?原来是我太年轻
前端·人工智能·后端
ZC跨境爬虫11 小时前
Apple官网复刻第二阶段day_6:(统一页脚模块封装+CSS公共复用体系落地)
前端·css·ui·重构·html
恋猫de小郭12 小时前
Flutter 凉了没?Flutter 2026 的未来行程和规划,一些有趣的变化
android·前端·flutter
Beginner x_u12 小时前
前端手动实现大文件分片上传调度层:分片计算、并发上传与断点续传
前端·状态模式·断点续传·大文件分片上传