Documentation

Convert a PDF to PDF/A in Go

Convert produces a PDF/A-1b conformant rewrite: pre-emptive fixups, a verify/fix loop, and rasterization as a last resort, with residual issues reported.

Convert produces a PDF/A conformant rewrite. It runs pre-emptive fixups, then a verify/fix loop, and rasterizes pages as a last resort when no in-place fixer can repair them. The output spills to a temp file when it is large, so always Close() the result.

convert.go
cr, err := gopdfrab.Convert(path, gopdfrab.PDFA1B)
if err != nil {
	log.Fatal(err)
}
defer cr.Close() // releases the output (a large one spills to a temp file)

if err := cr.Save("out.pdf"); err != nil {
	log.Fatal(err)
}

fmt.Println(cr.Iterations)      // how many verify/fixup passes it took
fmt.Println(cr.Result.Valid)    // true if the output is fully PDF/A conformant

Conversion is also available on an already-open document, on in-memory data, across a batch of files, and the result always exposes any residual issues that survived every remediation pass.

convert_variants.go
// Converting an open document
cr, err := doc.Convert(gopdfrab.PDFA1B)
defer cr.Close()

// Converting in-memory data
cr, err = gopdfrab.ConvertBytes(data, gopdfrab.PDFA1B)

// Converting multiple files concurrently
results, err := gopdfrab.ConvertAll(paths, gopdfrab.PDFA1B)
if err != nil {
	log.Fatal(err)
}
for _, r := range results {
	if r.Err != nil {
		log.Println(r.Path, r.Err)
		continue
	}
	fmt.Println(r.Path, r.Result.Result.Valid) // r.Result is a ConvertResult
}

// Inspecting residual issues after conversion
residual := cr.Residual()
for _, iss := range residual {
	c := iss.Check()
	fmt.Println(c.Clause(), c.Name())
	fmt.Println(iss.Page(), iss.Messages())
}

The loop is the important part. Fixing one problem can expose or create another — embedding a font changes the resource dictionary, which the object-model checks then see for the first time — so conversion re-verifies after each pass and repeats until the document converges or Options.MaxIterations is reached. A result is only reported valid if an independent verification pass says so.

Anything that could not be repaired is reported rather than hidden. Check Residual() before treating a conversion as complete: a document that needed an unembeddable font, or that lost an unrecoverable object during damage recovery, will say so there.

Conforming is not the same as unchanged
A page blanked during conversion still verifies clean. If visual equivalence matters, enable the fidelity check — it renders both sides and reports a per-page comparison.

Converting a PDF to PDF/A, step by step

  1. Open or name the document — Call Convert with a path, or ConvertDocument with a document you already opened. Both take the target profile — PDFA1B today.
  2. Let the verify/fix loop run — Conversion applies pre-emptive fixups, then re-verifies and fixes repeatedly until the document converges or Options.MaxIterations is reached. Pages no in-place fixer can repair are rasterized as a last resort.
  3. Check the residual issues — Read Residual() before treating the conversion as complete. Anything that could not be repaired — an unembeddable font, an object lost during damage recovery — is reported there rather than hidden.
  4. Confirm the appearance survived — A page blanked during conversion still verifies clean, so run the fidelity check when visual equivalence matters. It renders both sides and reports a per-page comparison.
  5. Write the output and close the result — Save writes to a file and WriteTo streams to any io.Writer. The output spills to a temp file when it is large, so always Close() the result.

See fidelity for that, streaming and batching for writing the output, and the browser converter to try it on a file first.