Голанг обрабатывает PDF

Go

На работе мы часто сталкиваемся с некоторыми проблемами при обработке файлов pdf.Существует тысяча способов справиться с тысячей видов pdf.

Я суслик, поэтому в этой статье будут перечислены все сценарии обработки pdf, с которыми я столкнулся, с точки зрения суслика, например:

pdf渲染
pdf校验
pdf加水印
pdf获取页数
pdf合并
pdf拆分
修复受损pdf
pdf转png
识别pdf中的字体
pdf解密
...

Большая часть этой статьи представляет собой список проблем сцены, вы можете извлечь интересующие вас части в соответствии с заголовком для просмотра.

Я не особенно профессионален во многих вопросах PDF.Если у вас есть какие-либо вопросы или вопросы, пожалуйста, не стесняйтесь общаться со мной.


1. Отрисовка HTML-страницы в формате PDF

Чтобы отобразить pdf на основе html-страницы, я использовал следующие две схемы:

  • wkhtmltopdf
  • chromedp

1. Рендерим pdf с помощью wkhtmltopdf

wkhtmltopdfИнструмент командной строки для рендеринга HTML-страниц в PDF, основанный на движке рендеринга Qt WebKit.

Использование относительно простое:

## 将一个静态html页面打印成pdf
$ wkhtmltopdf input.html output.pdf

## 将一个网页打印成pdf
$ wkhtmltopdf https://www.google.com output.pdf

Параметры wkhtmltopdf очень богаты, например:

Поддерживает отправку HTTP-запросов, подходит для рендеринга специально разработанных веб-страниц в файлы PDF:

$ wkhtmltopdf --help
...
--post <name> <value>           Add an additional post field (repeatable)
...

Поддержка сценариев javascript для изменения html перед рендерингом pdf:

$ wkhtmltopdf --run-script "javascript:(function(){document.getElementsByClassName('dom_class_name')[0].style.display = 'none'}())" page input.html output.pdf

Более подробные параметры см.Официальная документация сайта

Если вы используете язык Go, есть также сторонний пакет, который включает использование wkhtmltopdf:go-wkhtmltopdf

2. Используйте chromedp для рендеринга PDF

chromedp— это пакет в Go, который обеспечивает более быстрый и простой способ управления браузерами, поддерживающими протокол Chrome DevTools, без внешних зависимостей (таких как Selenium или PhantomJS).

Как пользоваться:

package main

import (
	"context"
	"io/ioutil"

	"github.com/chromedp/cdproto/page"
	"github.com/chromedp/chromedp"
	"errors"
)

func main(){
    err := ChromedpPrintPdf("https://www.google.com", "/path/to/file.pdf")
    if err != nil {
        fmt.Println(err)
        return
    }
}

func ChromedpPrintPdf(url string, to string) error {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	var buf []byte
	err := chromedp.Run(ctx, chromedp.Tasks{
		chromedp.Navigate(url),
		chromedp.WaitReady("body"),
		chromedp.ActionFunc(func(ctx context.Context) error {
			var err error
			buf, _, err = page.PrintToPDF().
				Do(ctx)
			return err
		}),
	})
	if err != nil {
	    return fmt.Errorf("chromedp Run failed,err:%+v", err)
	}

	if err := ioutil.WriteFile(to, buf, 0644); err != nil {
	    return fmt.Errorf("write to file failed,err:%+v", err)
	}

	return nil
}

2. Водяные знаки PDF

Инструменты, которые я изучил, которые поддерживают водяные знаки PDF:

  • unidoc/unipdf
  • pdfcpu

1.unidoc/unipdf

unidocплатформа разработанаunipdfЭто библиотека PDF, написанная на языке Go, которая предоставляет режимы использования API и CLI и поддерживает следующие функции:

$ unipdf -h
...
Available Commands:
  decrypt     Decrypt PDF files
  encrypt     Encrypt PDF files
  explode     Explodes the input file into separate single page PDF files
  extract     Extract PDF resources
  form        PDF form operations
  grayscale   Convert PDF to grayscale
  help        Help about any command
  info        Output PDF information
  merge       Merge PDF files
  optimize    Optimize PDF files
  passwd      Change PDF passwords
  rotate      Rotate PDF file pages
  search      Search text in PDF files
  split       Split PDF files
  version     Output version information and exit
  watermark   Add watermark to PDF files
...

Добавить водяной знак в режиме CLI

$ unipdf watermark in.pdf watermark.png -o out.pdf

Watermark successfully applied to in.pdf
Output file saved to out.pdf

Используйте API для добавления водяного знака, вы можете обратиться напрямуюunipdf github example

Примечание: за лицензию на использование продуктов unidoc необходимо заплатить.

2.pdfcpu

pdfcpuЭто библиотека обработки PDF, написанная на языке Go, предоставляющая API и режим CLI для использования.

Поддерживаются следующие функции:

$ pdfcpu help
...
The commands are:

   attachments list, add, remove, extract embedded file attachments
   changeopw   change owner password
   changeupw   change user password
   decrypt     remove password protection
   encrypt     set password protection
   extract     extract images, fonts, content, pages, metadata
   fonts       install, list supported fonts
   grid        rearrange pages or images for enhanced browsing experience
   import      import/convert images to PDF
   info        print file info
   merge       concatenate 2 or more PDFs
   nup         rearrange pages or images for reduced number of pages
   optimize    optimize PDF by getting rid of redundant page resources
   pages       insert, remove selected pages
   paper       print list of supported paper sizes
   permissions list, set user access permissions
   rotate      rotate pages
   split       split multi-page PDF into several PDFs according to split span
   stamp       add, remove, update text, image or PDF stamps for selected pages
   trim        create trimmed version of selected pages
   validate    validate PDF against PDF 32000-1:2008 (PDF 1.7)
   version     print version
   watermark   add, remove, update text, image or PDF watermarks for selected pages
...

Добавьте водяной знак на изображение с помощью инструмента CLI:

$ pdfcpu watermark add -mode image 'voucher_watermark.png' 's:1 abs, rot:0' in.pdf out.pdf

вызовите API, чтобы добавить водяной знак

package main

import (
	"github.com/pdfcpu/pdfcpu/pkg/api"
	"github.com/pdfcpu/pdfcpu/pkg/pdfcpu"
)

func main() {
	onTop := false
	wm, _ := pdfcpu.ParseImageWatermarkDetails("watermark.png", "s:1 abs, rot:0", onTop)
	api.AddWatermarksFile("in.pdf", "out.pdf", nil, wm, nil)
}

3. Слияние PDF

  • cpdf
  • unipdfc
  • pdfcpu

1. Объединить pdf с помощью cpdf

cpdfЭто бесплатная библиотека инструментов командной строки PDF с открытым исходным кодом с богатыми функциями, такими как:

  • Merge PDF files together, or split them apart
  • Encrypt and decrypt
  • Scale, crop and rotate pages
  • Read and set document info and metadata
  • Copy, add or remove bookmarks
  • Stamp logos, text, dates, page numbers
  • Add or remove attachments
  • Losslessly compress PDF files

Объединить PDF-файлы:

$ cpdf -merge input1.pdf input2.pdf -o output.pdf

2. Объединить pdf с помощью unipdf

$ unipdf merge output.pdf input1.pdf input2.pdf

Используйте API для слияния PDF, ссылкаunpdf github example

3. Объединить pdf с помощью pdfcpu

$ pdfcpu merge output.pdf input1.pdf input2.pdf

Примечание. pdfcpu поддерживает только файлы PDF с версиями ниже PDF V1.7.

4. Разделить PDF

  • cpdf
  • unipdf
  • pdfcpu

1. Разделить pdf с помощью cpdf

## 逐页拆分成单个pdf
$ cpdf -split in.pdf 1 even -chunk 1 -o ./out%%%.pdf

2. Разделить pdf с помощью unipdf

## 将第一页拆分出来
$ unipdf split input.pdf out.pdf 1-1

Разделить pdf с помощью API, ссылкаunipdf github examples

3. Разделить PDF с помощью pdfcpu

$ pdfcpu split in.pdf .

5. Преобразование PDF в изображение

  • mupdf
  • xpdf

1. Используйте mupdf для работы с pdf в изображение

MuPDF is a lightweight PDF, XPS, and E-book viewer.

MuPDF consists of a software library, command line tools, and viewers for various platforms.

После загрузки mupdf вы получаете некоторые инструменты, такие как:

mupdf               
pdfdraw
pdfinfo             
pdfclean            
pdfextract          
pdfshow             
xpsdraw

вpdfdrawМожет использоваться для преобразования изображений

$ pdfdraw -o out%d.png in.pdf

2. Используйте xpdf для работы с pdf в изображение

xpdfЭто бесплатный PDF Toolkit, включая анализ текста, преобразование изображения, преобразование HTML и т. Д.

Скачав пакет, вы можете получить ряд инструментов:

pdfdetach 
pdffonts  
pdfimages 
pdfinfo   
pdftohtml 
pdftopng  
pdftoppm  
pdftops   
pdftotext

Из названия можно примерно понять полезность каждого инструмента.

## 使用pdftopng将pdf转换成png
$ pdftopng in.pdf out-prefix

Шесть, расшифровка PDF

Я часто сталкиваюсь со сценарием, когда при чтении pdf-файла сообщается об ошибке: файл зашифрован

Но как это решить без пароля?

  • расшифровать с помощью qpdf

использоватьqpdfВыполните принудительную расшифровку.В некоторых случаях расшифровка может быть успешной, но в некоторых случаях расшифровка может быть неудачной.

qpdf — это инструмент для работы с PDF, поддерживающий командную строку.

$ qpdf --decrypt in.pdf out.pdf
  • расшифровать с помощью pdfcpu
$ pdfcpu decrypt encrypted.pdf output.pdf

Когда есть пароль, его можно расшифровать с помощью пароля:

  • расшифровать pdf с помощью unipdf
$ unipdf decrypt -p pass -o output.pdf input.pdf

Семь, распознавание PDF

Я часто сталкиваюсь с некоторыми сценариями, такими как распознавание того, является ли файл файлом pdf, распознавание текста в pdf, распознавание изображений в pdf и т. д.

1. Распознать текст в PDF

Как используется здесь, pdf xpdf анализирует текст, а затем использует некоторые манипуляции со строками регулярных выражений или бизнес-анализ.

  • использоватьxpdf/pdftotextРазобрать текст в pdf
$ pdftotext input.pdf output.txt
  • использоватьunipdfРазобрать текст в pdf
$ unipdf extract text input.pdf

Разобрать текст в формате pdf с помощью API, ссылкаunipdf github examples

  • Разбор данных PDF с использованием информации координаты

Вышеупомянутое состоит в том, чтобы сначала проанализировать текст pdf, а затем обработать его в соответствии с бизнес-процессами.

Другой способ состоит в том, чтобы проанализировать PDF-файл в соответствии с положением координат, что является более гибким и общим, с использованиемpdflib/tet

## 输入一组坐标,即可按照坐标解析pdf中的数据
$ tet --pageopt "includebox={{38 707.93 243.91 716.93}}" input.pdf

Координаты могут использовать tet для анализа pdf, чтобы получить файл tetml, который содержит информацию о координатах:

$ tet --tetml input.pdf

Конечно, вы также можете использовать некоторые другие методы для получения информации о координатах данных в pdf, такие как nodejs и т. д.

Уведомление:pdflib/tetЭто платное программное обеспечение, но согласно официальной документации, tet предоставляет базовые функции, и вам не нужно приобретать лицензию для обработки pdf-файлов объемом не более 10 страниц или менее 1M.

pdflib/tetОн предоставляет инструменты командной строки и поддержку языков SDK, таких какC/C++/Java/.NET/Perl/PHP/Python/Ruby/SwiftНо язык Go пока не поддерживается, поэтому на данный момент есть только два варианта gopher: CLI ИЛИ CGO

8. Восстановить поврежденные PDF-файлы

Есть некоторые PDF-файлы, которые выглядят нормально при открытии на компьютере, но являются ненормальными при обнаружении кодом, например при попытке использовать стороннюю библиотеку для анализа (поврежденного) PDF-файла в Go:

import (
    "fmt"
    "github.com/rsc.io/pdf"
)

func main() {
    filePath := "path/to/your/broken.pdf"
    _, err := pdf.Open(filePath)
	if err != nil {
		fmt.Println("open pdf failed,err:", err.Error())
		return
	}
}

После запуска вы получите такой результат:

open pdf failed,err: malformed PDF: cross-reference table not found: {5 0 obj}<</Contents 6 0 R /Group <</CS /DeviceRGB /S /Transparency /Type /Group>> /MediaBox [0 0 595.27600098 841.89001465] /Parent 3 0 R /Type /Page>>

Компьютер включается нормально, но программа читает ошибку!

В это время, если вы попытаетесь открыть pdf-файл на компьютере, затем сохраните его как новый pdf-файл, а затем используете код для его обнаружения, вы обнаружите, что он был восстановлен!

Отлично, проблема решена!

И так, если у меня 1000 pdf файлов, вы же не хотите открывать по одному и сохранять как? Как вы можете быть в состоянии?Так что, если есть функция пакетного восстановления просто отлично

После долгих поисков в интернете я нашел примерно три решения:

  • Используя Acrobat SDK, вызовите SDK всохранить как функцию, можно реализовать эффект открытия сохранения как на компе
  • восстановление pdf с помощью ghostscript
  • использоватьmupdfсделать ремонт пдф

Здесь я только проверил, что третий способ выполним, здесь я используюmupdf-0.9-linux-amd64Проверить эту версию

После загрузки пакета я получил один из исполняемых файлов:pdfclean

$ pdfclean broken.pdf repaired.pdf

+ pdf/pdf_xref.c:160: pdf_read_trailer(): cannot recognize xref format: '%'
| pdf/pdf_xref.c:481: pdf_load_xref(): cannot read trailer
\ pdf/pdf_xref.c:537: pdf_open_xref_with_stream(): trying to repair

Судя по выводу, mupdf попробовал процесс восстановления

После получения нового файла PDF попробуйте открыть его с помощью предыдущего кода Go, это нормально.

Осталось написать bash-скрипт, пакетно фиксить и цель достигнута!

Девять, информация об идентификации шрифта файла PDF

Иногда необходимо поддерживать согласованность нескольких текстовых шрифтов PDF, чтобы не анализировать, какие шрифты используются в PDF, в настоящее время вы можете использоватьxpdf/pdffontsВыполнить анализ шрифта

$ pdffonts input.pdf
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
NimbusSanL-Regu                      CID TrueType      Identity-H       yes no  yes     10  0
NimbusSanL-Bold                      CID TrueType      Identity-H       yes no  yes     20  0

Другое введение Libiray

Это библиотека с открытым исходным кодом C++, которая поддерживает создание PDF-файлов, объединение PDF-файлов, манипулирование текстом водяных знаков изображения и т. д.

Для gopher, чтобы использовать эту библиотеку, вам нужно инкапсулировать слой кода CGO.

Это библиотека PDF, реализованная на языке Go, которую можно использовать для чтения информации в формате PDF, такой как чтение содержимого PDF/номера страниц/шрифта и т. д. Для получения подробной информации см.Документация


Представляя так много сторонних библиотек, он просто разнообразен, каждая проявляет свои магические силы. Некоторые функции повторяются в большинстве библиотек, и какие проблемы могут возникнуть при конкретном использовании, зависит от реальной ситуации.

Надеюсь, что эти резюме будут полезны читателям


Ссылаться на: