最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go處理PDF的實(shí)現(xiàn)代碼

 更新時(shí)間:2020年01月02日 09:36:40   作者:poisoner  
這篇文章主要介紹了Go處理PDF的實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

工作中經(jīng)常會(huì)遇到一些pdf文件處理的問(wèn)題,一千種pdf有一千種處理方式,每次都是絞盡腦汁和這些pdf戰(zhàn)斗到底。

本人又是一個(gè)gopher,所以這篇文章會(huì)以一個(gè)goper的視角,列舉一下我所經(jīng)歷過(guò)的每一種pdf處理場(chǎng)景,比如:

pdf渲染
pdf校驗(yàn)
pdf加水印
pdf獲取頁(yè)數(shù)
pdf合并
pdf拆分
修復(fù)受損pdf
pdf轉(zhuǎn)png
識(shí)別pdf中的字體
pdf解密
...

本文大多是場(chǎng)景問(wèn)題的羅列,可以根據(jù)標(biāo)題摘取自己有興趣的部分查看

很多pdf的問(wèn)題我也不是特別專業(yè),如果問(wèn)題或者疑問(wèn)歡迎與我交流

一、HTML頁(yè)面渲染PDF

根據(jù)html頁(yè)面渲染pdf,我使用過(guò)以下兩種方案:

  • wkhtmltopdf
  • chromedp

1. 使用wkhtmltopdf渲染pdf

wkhtmltopdf是一個(gè)命令行工具,用于將HTML頁(yè)面渲染為PDF,基于Qt WebKit渲染引擎實(shí)現(xiàn)

使用方式比較簡(jiǎn)單:

## 將一個(gè)靜態(tài)html頁(yè)面打印成pdf
$ wkhtmltopdf input.html output.pdf

## 將一個(gè)網(wǎng)頁(yè)打印成pdf
$ wkhtmltopdf https://www.google.com output.pdf

wkhtmltopdf的參數(shù)很豐富,比如:

支持發(fā)送 http post請(qǐng)求,適合將自定義開(kāi)發(fā)的網(wǎng)頁(yè)渲染成pdf文件:

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

支持javascript腳本,在渲染pdf前對(duì)html進(jìn)行修改:

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

更多詳細(xì)參數(shù)可看官網(wǎng)文檔

如果你使用Go語(yǔ)言,還有一個(gè)第三方包,是對(duì)wkhtmltopdf的使用封裝:go-wkhtmltopdf

2. 使用chromedp渲染pdf

chromedp是一種在Go語(yǔ)言中以更快,更簡(jiǎn)單的方式來(lái)驅(qū)動(dòng)支持Chrome DevTools協(xié)議的瀏覽器的軟件包,而無(wú)需外部依賴((例如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
}

二、PDF加水印

我了解到的支持pdf加水印的工具有:

  • unidoc/unipdf
  • pdfcpu

1.unidoc/unipdf

unidoc平臺(tái)開(kāi)發(fā)的unipdf是一款用Go語(yǔ)言編寫的PDF庫(kù),提供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的產(chǎn)品需要付費(fèi)購(gòu)買license使用

2.pdfcpu

pdfcpu 是一個(gè)用Go語(yǔ)言編寫的PDF處理庫(kù),提供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

調(diào)用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)
}

三、PDF合并

  • cpdf
  • unipdfc
  • pdfcpu

1.使用cpdf合并pdf

cpdf是一個(gè)開(kāi)源免費(fèi)的PDF命令行工具庫(kù),有豐富的功能,比如:

  • 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.使用unipdf合并pdf

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

使用API合并pdf,參考unpdf github example

3.使用pdfcpu合并pdf

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

注意: pdfcpu只支持版本低于PDF V1.7的pdf文件

四、拆分PDF

  • cpdf
  • unipdf
  • pdfcpu

1.使用cpdf拆分pdf

## 逐頁(yè)拆分成單個(gè)pdf
$ cpdf -split in.pdf 1 even -chunk 1 -o ./out%%%.pdf

2. 使用unipdf拆分pdf

## 將第一頁(yè)拆分出來(lái)
$ unipdf split input.pdf out.pdf 1-1

使用api拆分pdf,參考unipdf github examples

3.使用pdfcpu拆分pdf

$ pdfcpu split in.pdf .

五、PDF轉(zhuǎn)圖片

  • mupdf
  • xpdf

1. 使用mupdf操作pdf轉(zhuǎn)圖片

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可用來(lái)轉(zhuǎn)換圖片

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

注意: mupdf不支持mac OS

2. 使用xpdf操作pdf轉(zhuǎn)圖片

xpdf是一個(gè)免費(fèi)的PDF工具包,包括文字解析,圖片轉(zhuǎn)換,html轉(zhuǎn)換等

下載該軟件包后,可以得到一系列的工具:

pdfdetach
pdffonts 
pdfimages
pdfinfo  
pdftohtml
pdftopng 
pdftoppm 
pdftops  
pdftotext

從名稱上看,大致能看出來(lái)每一個(gè)工具的用處

## 使用pdftopng將pdf轉(zhuǎn)換成png
$ pdftopng in.pdf out-prefix

六、PDF解密

經(jīng)常會(huì)遇到一種場(chǎng)景,讀取pdf文件的時(shí)候發(fā)現(xiàn)會(huì)報(bào)錯(cuò):文件被加密

但是在沒(méi)有密碼的情況下怎么解決呢?

  • 使用qpdf解密

使用qpdf進(jìn)行強(qiáng)制解密,有些情況是可以解密成功的,但是有些情況也不一定能解密成功

qpdf是一個(gè)支持命令行的pdf工具

$ qpdf --decrypt in.pdf out.pdf

使用pdfcpu解密

$ pdfcpu decrypt encrypted.pdf output.pdf

當(dāng)有密碼的情況下,可以使用密碼解密:

使用unipdf解密pdf

$ unipdf decrypt -p pass -o output.pdf input.pdf

七、PDF識(shí)別

經(jīng)常會(huì)遇到一些場(chǎng)景,比如識(shí)別一個(gè)文件是不是pdf文件,識(shí)別pdf中的文字,識(shí)別pdf中的圖片等

1.識(shí)別pdf中的文字

這里使用xpdf將pdf中的文字解析出來(lái),然后再使用一些字符串操作或者正則表達(dá)式進(jìn)行業(yè)務(wù)分析

使用xpdf/pdftotext解析pdf中的文本

$ pdftotext input.pdf output.txt

使用unipdf解析pdf中的文本

$ unipdf extract text input.pdf

使用API解析pdf文本,參考unipdf github examples

使用坐標(biāo)信息解析pdf數(shù)據(jù)

上面都是先解析出pdf的文本,再根據(jù)業(yè)務(wù)進(jìn)行處理

還有一種方式是按照坐標(biāo)位置解析pdf,這種方式更加靈活以及通用,利用的是pdflib/tet

## 輸入一組坐標(biāo),即可按照坐標(biāo)解析pdf中的數(shù)據(jù)
$ tet --pageopt "includebox={{38 707.93 243.91 716.93}}" input.pdf

坐標(biāo)可以使用tet對(duì)pdf進(jìn)行分析得到一個(gè)tetml文件,里面包含了坐標(biāo)信息:

$ tet --tetml input.pdf

當(dāng)然也可以用一些其他的方式獲取pdf中數(shù)據(jù)的坐標(biāo)信息,比如nodejs等

注意: pdflib/tet是收費(fèi)軟件,但是根據(jù)官方文檔說(shuō)明,tet提供基礎(chǔ)功能,處理不超過(guò)10頁(yè)或者小于1M的pdf文件是不需要購(gòu)買license的

pdflib/tet提供了命令行工具以及多種語(yǔ)言的sdk支持,比如C/C++/Java/.NET/Perl/PHP/Python/Ruby/Swift 但目前還不支持Go語(yǔ)言,所以對(duì)于gopher而言目前只有兩種選擇:CLI OR CGO

八、修復(fù)受損PDF文件

有一些pdf文件在電腦上打開(kāi)時(shí),顯示正常,但是用代碼檢測(cè)卻是不正常的,比如在Go中嘗試用一個(gè)第三方庫(kù)去解析一個(gè)(受損的)pdf:

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
  }
}

運(yùn)行后會(huì)得到這樣一個(gè)結(jié)果:

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>>

電腦打開(kāi)正常,程序卻讀取錯(cuò)誤!

這時(shí)候如果嘗試在電腦上打開(kāi)pdf,然后另存為一個(gè)新的pdf文件,再用代碼去檢測(cè),會(huì)發(fā)現(xiàn)竟然修復(fù)了!

太好了,問(wèn)題解決!

等等,如果我有1000張pdf文件,難道要逐個(gè)打開(kāi)并另存為?這怎么能忍? 所以如果有一種批量修復(fù)的功能就好了

在網(wǎng)上找了很久,大概得到三種解決方案:

  • 利用 Acrobat SDK,調(diào)用SDK中的另存為功能,可以實(shí)現(xiàn)電腦打開(kāi)另存為的效果
  • 利用ghostscript進(jìn)行pdf修復(fù)
  • 利用mupdf進(jìn)行pdf修復(fù)

這里我只驗(yàn)證了第三種方式是可行的,這里我使用mupdf-0.9-linux-amd64這個(gè)版本進(jìn)行驗(yàn)證

下載軟件包后,得到其中一個(gè)可執(zhí)行文件: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

從輸出結(jié)果來(lái)看,mupdf嘗試了修復(fù)處理

得到新的pdf文件之后,再用前面的Go代碼嘗試打開(kāi),就正常了

剩下的就是寫一個(gè)bash腳本,批量修復(fù),目標(biāo)達(dá)成!

九、識(shí)別一個(gè)PDF文件的字體信息

有時(shí)候要使多個(gè)pdf文本字體保持一致,免不得要去分析pdf中都使用了哪些字體,這時(shí)候可以使用xpdf/pdffonts進(jìn)行字體分析

$ 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介紹:

PDF-Writer
這是一個(gè)C++的開(kāi)源庫(kù),支持創(chuàng)建pdf,合并pdf,圖片水印文字操作等

對(duì)于gopher來(lái)講,要使用這個(gè)庫(kù),需要封裝一層CGO代碼才可以

rsc/pdf
這是一個(gè)Go語(yǔ)言實(shí)現(xiàn)的pdf庫(kù),可以用于讀取pdf信息,比如讀取pdf內(nèi)容/頁(yè)數(shù)/字體等... 具體可以參考文檔

介紹了這么多第三方庫(kù),簡(jiǎn)直就是五花八門,各顯神通。有些功能在大多數(shù)庫(kù)中都是有重復(fù)的,具體使用中會(huì)遇到什么問(wèn)題,還是要看實(shí)際情況如何。

希望這些總結(jié)能夠?qū)ψx者有所幫助

參考:

wkhtmltopdf
xpdf
cpdf
qpdf
unidoc
pdflib/tet
pdfwriter
mupdf
pdfcpu

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Go語(yǔ)言之Goroutine與信道異常處理

    Go語(yǔ)言之Goroutine與信道異常處理

    這篇文章主要給大家介紹得是Go語(yǔ)言Goroutine與信道異常處理,Goroutine 之間通信是通過(guò) channel 通信的,想詳細(xì)了解得小伙伴跟小編一起來(lái)學(xué)習(xí)下面文章內(nèi)容吧
    2021-10-10
  • Golang Gorm 更新字段save、update、updates

    Golang Gorm 更新字段save、update、updates

    在gorm中,批量更新操作可以通過(guò)使用Update方法來(lái)實(shí)現(xiàn),本文主要介紹了Golang Gorm 更新字段save、update、updates,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • Go語(yǔ)言七篇入門教程五文件及包

    Go語(yǔ)言七篇入門教程五文件及包

    本章節(jié)主要介紹go語(yǔ)言的文件處理與包管理,本文是Go語(yǔ)言七篇入門教程系列篇,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-11-11
  • golang方法中receiver為指針與不為指針的區(qū)別詳析

    golang方法中receiver為指針與不為指針的區(qū)別詳析

    這篇文章主要給大家介紹了關(guān)于golang方法中receiver為指針與不為指針區(qū)別的相關(guān)資料,其實(shí)最大的區(qū)別應(yīng)該是指針傳遞的是對(duì)像的引用,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-10-10
  • go實(shí)現(xiàn)冒泡排序算法

    go實(shí)現(xiàn)冒泡排序算法

    冒泡排序算法是數(shù)據(jù)結(jié)構(gòu)中常用的一種算法,本文就介紹了go實(shí)現(xiàn)冒泡排序算法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • SpringEvent優(yōu)雅解耦時(shí)連續(xù)兩個(gè)bug的解決方案

    SpringEvent優(yōu)雅解耦時(shí)連續(xù)兩個(gè)bug的解決方案

    這篇文章主要為大家介紹了SpringEvent優(yōu)雅解耦時(shí)連續(xù)兩個(gè)bug的解決方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 使用Go初始化Struct的方法詳解

    使用Go初始化Struct的方法詳解

    面向?qū)ο缶幊陶Z(yǔ)言最基礎(chǔ)的概念就是類(class),不過(guò)Go語(yǔ)言并沒(méi)有類的概念,所以使用Go語(yǔ)言開(kāi)發(fā)時(shí),我們一般會(huì)用struct(結(jié)構(gòu)體)來(lái)模擬面向?qū)ο笾械念?下面我們來(lái)介紹幾種創(chuàng)建struct類型變量的方法,需要的朋友可以參考下
    2024-01-01
  • Go語(yǔ)言學(xué)習(xí)之結(jié)構(gòu)體和方法使用詳解

    Go語(yǔ)言學(xué)習(xí)之結(jié)構(gòu)體和方法使用詳解

    這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言中結(jié)構(gòu)體和方法的使用,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語(yǔ)言有一定的幫助,需要的可以參考一下
    2022-04-04
  • go?mod詳細(xì)使用教程

    go?mod詳細(xì)使用教程

    go mod是go的一個(gè)模塊管理工具,用來(lái)代替?zhèn)鹘y(tǒng)的GOPATH方案,下面這篇文章主要給大家介紹了關(guān)于go?mod詳細(xì)使用的相關(guān)資料,文中通過(guò)圖文以及實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • Golang基于泛化調(diào)用與Nacos實(shí)現(xiàn)Dubbo代理

    Golang基于泛化調(diào)用與Nacos實(shí)現(xiàn)Dubbo代理

    這篇文章主要為大家詳細(xì)介紹了Golang如何基于泛化調(diào)用與Nacos實(shí)現(xiàn)Dubbo代理,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-04-04

最新評(píng)論

汶上县| 津南区| 镇沅| 庆城县| 杂多县| 玉山县| 武邑县| 策勒县| 黄陵县| 江阴市| 水城县| 乌审旗| 申扎县| 松江区| 肥城市| 顺昌县| 孟津县| 烟台市| 中超| 吉木乃县| 农安县| 棋牌| 香港| 米易县| 昌乐县| 西城区| 宣威市| 将乐县| 彭水| 金溪县| 新和县| 城口县| 通山县| 临城县| 临猗县| 新宁县| 洛南县| 闻喜县| 饶河县| 南澳县| 鄢陵县|