Skip to content

Save Documents

This guide explains how to save PDF documents and the available save options.

// Save existing document
using document = await pdfium.openDocument(data);
const bytes = document.save();
await fs.writeFile('output.pdf', bytes);
// Save new document
using builder = pdfium.createDocument();
// ... add content ...
const bytes = builder.save();
await fs.writeFile('output.pdf', bytes);

Both PDFiumDocument.save() and PDFiumDocumentBuilder.save() accept options:

interface SaveOptions {
flags?: SaveFlags;
version?: number;
}
import { SaveFlags } from '@scaryterry/pdfium';
FlagValueDescription
None0Default full save
Incremental1Append changes (preserves signatures)
NoIncremental2Force full rewrite
RemoveSecurity3Remove encryption

Specify the PDF version as a number:

VersionValueReleased
PDF 1.4142001
PDF 1.5152003
PDF 1.6162004
PDF 1.7172006
PDF 2.0202017

Rewrites the entire PDF:

const bytes = document.save();
// or
const bytes = document.save({ flags: SaveFlags.None });

Characteristics:

  • Creates optimised file
  • May invalidate digital signatures
  • Removes document history
  • Usually smaller file size

Appends changes to the end of the file:

const bytes = document.save({ flags: SaveFlags.Incremental });

Characteristics:

  • Preserves digital signatures
  • Maintains document history
  • Faster for large documents with small changes
  • File size grows with each save

Use when:

  • Document has digital signatures
  • Audit trail is required
  • Making small modifications

Forces full rewrite even if incremental would be possible:

const bytes = document.save({ flags: SaveFlags.NoIncremental });

Removes encryption (requires correct password to open first):

// Open with password
using document = await pdfium.openDocument(data, { password: 'secret' });
// Save without encryption
const bytes = document.save({ flags: SaveFlags.RemoveSecurity });
// Save as PDF 1.7
const bytes = document.save({ version: 17 });
// Save as PDF 2.0
const bytes = document.save({ version: 20 });
FeatureMinimum Version
Basic PDF1.4
Compressed objects1.5
AES encryption1.6
PDF/A-21.7
New annotation types2.0
import { DocumentError, PDFiumErrorCode } from '@scaryterry/pdfium';
try {
const bytes = document.save();
await fs.writeFile('output.pdf', bytes);
} catch (error) {
if (error instanceof DocumentError) {
if (error.code === PDFiumErrorCode.DOC_SAVE_FAILED) {
console.error('Failed to save document:', error.message);
}
}
throw error;
}
const bytes = document.save();
// bytes is Uint8Array
import { promises as fs } from 'fs';
const bytes = document.save();
await fs.writeFile('output.pdf', bytes);
import { createWriteStream } from 'fs';
const bytes = document.save();
const stream = createWriteStream('output.pdf');
stream.write(bytes);
stream.end();
// Express.js example
app.get('/download', async (req, res) => {
const data = await fs.readFile('document.pdf');
using pdfium = await PDFium.init();
using document = await pdfium.openDocument(data);
// Modify document...
const bytes = document.save();
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', 'attachment; filename="output.pdf"');
res.send(Buffer.from(bytes));
});
function downloadPDF(bytes: Uint8Array, filename: string) {
const blob = new Blob([bytes], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
link.click();
URL.revokeObjectURL(url);
}
// Usage
const bytes = document.save();
downloadPDF(bytes, 'output.pdf');
import { PDFium } from '@scaryterry/pdfium';
import { promises as fs } from 'fs';
async function upgradePDFVersion(inputPath: string, outputPath: string) {
const data = await fs.readFile(inputPath);
using pdfium = await PDFium.init();
using document = await pdfium.openDocument(data);
// Save as PDF 1.7
const bytes = document.save({ version: 17 });
await fs.writeFile(outputPath, bytes);
console.log(`Upgraded ${inputPath} to PDF 1.7`);
}
async function removePassword(
inputPath: string,
outputPath: string,
password: string
) {
const data = await fs.readFile(inputPath);
using pdfium = await PDFium.init();
using document = await pdfium.openDocument(data, { password });
const bytes = document.save({ flags: SaveFlags.RemoveSecurity });
await fs.writeFile(outputPath, bytes);
console.log('Password protection removed');
}
async function signaturePreservingSave(
inputPath: string,
outputPath: string
) {
const data = await fs.readFile(inputPath);
using pdfium = await PDFium.init();
using document = await pdfium.openDocument(data);
// Make modifications here...
// Save incrementally to preserve signatures
const bytes = document.save({ flags: SaveFlags.Incremental });
await fs.writeFile(outputPath, bytes);
console.log('Saved with signatures preserved');
}
import { promises as fs } from 'fs';
import path from 'path';
async function convertPDFVersions(
inputDir: string,
outputDir: string,
targetVersion: number
) {
using pdfium = await PDFium.init();
const files = await fs.readdir(inputDir);
const pdfFiles = files.filter(f => f.toLowerCase().endsWith('.pdf'));
await fs.mkdir(outputDir, { recursive: true });
for (const file of pdfFiles) {
const inputPath = path.join(inputDir, file);
const outputPath = path.join(outputDir, file);
try {
const data = await fs.readFile(inputPath);
using document = await pdfium.openDocument(data);
const bytes = document.save({ version: targetVersion });
await fs.writeFile(outputPath, bytes);
console.log(`Converted: ${file}`);
} catch (error) {
console.error(`Failed: ${file}`, error);
}
}
}
// Convert all PDFs to version 1.7
convertPDFVersions('./input', './output', 17);