This example demonstrates the standard open-edit-save pipeline with PDF documents, using different options on every step.
Introduction
The PDF documents, or documents in a Portable Document Format, developed by Adobe Corp, are widely used over all Internet and document management systems. PDF format has a crucial distinction from other formats such as DOCX, TXT, or HTML/CSS — it is a so-called fixed-layout format. The main purpose of PDF is to be platform-independent and store the exact representation of a document, — wherever and whenever this document is opened, it should provide the per-character and even a per-pixel fidelity. This means that a document, once created, is “baked” in terms of its representation and editability. While you can freely edit any DOCX document by adding, removing or moving any part of its content, and page layout is organically updated to fit newly added paragraphs or images (or pages are collapsed when text and other content is removed from the beginning or the middle of the document), the PDF documents sustain “frozen”. PDF documents have pages, but every word, character, pixel is strictly bound to every page and cannot be moved. In fact, PDF format doesn’t contain the definitions of paragraphs, titles, sentences, words and even letters — internally PDF document consists of pages, where every page contains a set of glyphs (visual character), where every glyph has coordinates where it is located on this page. Same for images and other visual elements. Words, text blocks, paragraphs and so on, visually identifiable by the users, who open PDF in some viewer like Adobe Reader, are nothing more than a set of symbols, displaced by coordinates over all the page to be “like a text”. For example, tables are nothing more than a set of the drawn lines to form a visual grid with glyphs, drawn in its cells. From this point of view, PDF format is much closer to raster or vector images like JPEG, PNG, or SVG, then to “truly” text documents like DOCX or TXT.
Concluding:
Editing the PDF documents like ordinary DOCX, TXT, or HTML is an extremely difficult and complex task.
Quality of editing the PDF document may be very close to what we can do with usual text documents, but it will never be 100%, especially when input PDF has quite complex formatting and content.
Due to the complexity of PDF format and a process of making it editable, this operation requires a lot of processing time and memory.
From its emergence the GroupDocs.Editor for Java had no support for editing the PDF documents. But starting from the version 26.7 we finally released this possibility! And this article explains in detail how to edit PDF document of any complexity like an ordinary text or WordProcessing document.
In two words
Editing of the PDF documents is the same as editing any other documents:
importcom.groupdocs.editor.Editor;importcom.groupdocs.editor.EditableDocument;importcom.groupdocs.editor.options.PdfLoadOptions;importcom.groupdocs.editor.options.PdfEditOptions;importcom.groupdocs.editor.options.PdfSaveOptions;importcom.groupdocs.editor.options.PdfCompliance;importcom.groupdocs.editor.options.PageRange;//0. Simple preparations of input data
Stringfilename="NET_Framework-protected.pdf";Stringpassword="password";StringinputPath="C:\\input\\"+filename;//1. Create a load options class with password
PdfLoadOptionsloadOptions=newPdfLoadOptions();loadOptions.setPassword(password);//2. Create edit options and tune/adjust if necessary
PdfEditOptionseditOptions=newPdfEditOptions();editOptions.setEnablePagination(true);//enable pagination for per-page processing in WYSIWYG-editor
editOptions.setPages(PageRange.fromStartPageTillEnd(3));//edit not all pages, but starting from 3rd and till the end
//3. Create Editor instance, load a document
Editoreditor=newEditor(inputPath,loadOptions);//4. Edit a document and generate EditableDocument
EditableDocumentoriginalDoc=editor.edit(editOptions);//5. Generate HTML/CSS, send it to WYSIWYG, edit there...and obtain edited version
StringoriginalContent=originalDoc.getEmbeddedHtml();StringeditedContent=originalContent.replace(".NET Framework","I love Java!!!");//6. Generate EditableDocument from edited content
EditableDocumenteditedDoc=EditableDocument.fromMarkup(editedContent,null);//7. Create and adjust save options
PdfSaveOptionssaveOptions=newPdfSaveOptions();saveOptions.setCompliance(PdfCompliance.Pdf20);//8. Save to a file or a stream
StringoutputPath="C:\\output\\"+filename;editor.save(editedDoc,outputPath,saveOptions);//9. Don't forget to dispose all resources
originalDoc.dispose();editedDoc.dispose();editor.dispose();
Loading
Class com.groupdocs.editor.options.PdfLoadOptions is responsible for loading the PDF files into the com.groupdocs.editor.Editor. It has only one property — a password of a String type. By default it is a null — no password is specified. This property is vital when an input document is encoded with a password. If a document is not encoded — property value is ignored whether it was specified or not.
Actually, when input PDF is not password-protected, the PdfLoadOptions is not necessary at all — the GroupDocs.Editor will automatically detect the PDF format and apply the default PdfLoadOptions by itself. However, specifying even default PdfLoadOptions will speed-up the document processing, because in this case the GroupDocs.Editor will not spend the processing time for the automatic format detection routine.
importcom.groupdocs.editor.Editor;importcom.groupdocs.editor.options.PdfLoadOptions;//Creating the default PDF loading options
PdfLoadOptionsloadOptions=newPdfLoadOptions();//Setting a password
loadOptions.setPassword("some_password");StringinputPdfPath="C:\\input\\NET_Framework-protected.pdf";//Loading a PDF without PDF load options
Editoreditor1=newEditor(inputPdfPath);//Loading a PDF with PDF load options
Editoreditor2=newEditor(inputPdfPath,loadOptions);
The next properties are inherited from the FixedLayoutEditOptionsBase:
boolean flag skipImages. By default it has a false value — images are not skipped and are preserved. However, if you need only textual information from the document, you can set this flag to true.
boolean flag enablePagination. It has the exact meaning as the same flag in the WordProcessingEditOptions. This flag sets the document conversion mode: the float (default value is false) or paginal (true). For the PDF and XPS documents it means the same:
When the float mode is selected, the document content will be converted to a pageless (float) HTML document, where there is only a single page (like any common web-document).
When the paginal mode is selected, the pages of the document will be preserved in the generated HTML document, like it can be seen in the PDF viewer like Adobe Reader.
Actually, the relevance and necessity of this mode relies mostly on your WYSIWYG-editor.
pages property of the PageRange type. PageRange is an immutable type, that holds a page range of any document, without relation to the specific document. And the pages property through a PageRange allows setting a page range, which should be processed. By default all the pages of the input document are processed (PageRange.isDefault() == true). You can choose the different ways to set a page range using different static methods from a PageRange class. Also pay attention — in PageRange pages are specified via page numbers, not via indexes, so they are 1-based, but not 0-based.
When the instance of a PdfEditOptions class is created and adjusted, you can pass it to the Editor.edit(IEditOptions editOptions) method and obtain an instance of EditableDocument class, which is ready for generating HTML/CSS markup and sending it to the client-side.
By the way, if a default PdfEditOptions instance is acceptable for you, i.e. you do not want to adjust its settings, you are allowed to omit PdfEditOptions creating at all — just call the Editor.edit() parameterless overload and the GroupDocs.Editor will internally generate and apply the default PdfEditOptions for the input PDF document.
Code sample below demonstrates all described in details:
importcom.groupdocs.editor.Editor;importcom.groupdocs.editor.EditableDocument;importcom.groupdocs.editor.options.PdfEditOptions;importcom.groupdocs.editor.options.PageRange;//0. Prepare path to your input PDF file
Stringfilename="Comparison for .NET.pdf";StringinputPdfPath="C:\\input\\"+filename;//1. Create Editor instance - we do not use PdfLoadOptions here
Editoreditor=newEditor(inputPdfPath);//2. Edit PDF document with default PdfEditOptions - no need to create and pass PdfEditOptions explicitly
EditableDocumentoriginalDefaultDoc=editor.edit();//3. Create and adjust PdfEditOptions for advanced edit
//3.1. Create instance of PdfEditOptions class with specified pagination mode (enabled)
PdfEditOptionseditOptions=newPdfEditOptions(true);//3.2. Set to skip images - now they will be omitted during processing
editOptions.setSkipImages(true);//3.3. Set a page range - only second and third pages (input document initially has 4 pages)
editOptions.setPages(PageRange.fromStartPageWithCount(2,2));//don't forget that page numbers are 1-based
//4. Edit the same PDF document with tuned edit options
EditableDocumenttunedDoc=editor.edit(editOptions);// Don't forget to dispose resources when work is done
originalDefaultDoc.dispose();tunedDoc.dispose();editor.dispose();
Stringproperty password — allows to protect the output PDF document with a specified password. By default is null — password-protection is not applied. When specified and is not a null or empty string, then the output PDF will be encrypted with RC4 (key length of 128 bit).
compliance property allows setting the PDF standards compliance level for output PDF. It has an enum type PdfCompliance, each value represents one specific PDF compliance level. By default is a PDF 1.7 (ISO 32000-1) standard.
optimizeMemoryUsageboolean flag, that allows to modify the process of generation of an output PDF document from an EditableDocument instance in such a way that this process will take a lesser memory consumption at the cost of the longer processing time. By default it has a false value, which means that the memory optimization is disabled for the sake of better performance. In case of extremely huge documents, enabling this property is vital in order to cope with OutOfMemoryError, especially on 32-bit processes.
fontEmbedding property of FontEmbeddingOptions type is responsible for embedding the font resources into the resultant PDF document. FontEmbeddingOptions is an enum that has several values, which allow to control which fonts should be embedded into PDF. By default fonts are not embedded at all (NotEmbed). When specifying the EmbedAll enum value, all used fonts in the document will be embedded inside the resultant PDF. When specifying the EmbedWithoutSystem — only those fonts, which are absent in the current operating system (where the GroupDocs.Editor is running).
Unlike the PdfLoadOptions and PdfEditOptions, which are optional when they are default (may be omitted during loading and editing respectively), the PdfSaveOptions is mandatory even if all its values are default.
Code sample below shows all necessary preparations (load and edit operations) and then saving in details.
importcom.groupdocs.editor.Editor;importcom.groupdocs.editor.EditableDocument;importcom.groupdocs.editor.options.PdfSaveOptions;importcom.groupdocs.editor.options.PdfCompliance;importcom.groupdocs.editor.options.FontEmbeddingOptions;importjava.io.ByteArrayOutputStream;//0. Prepare path to your input PDF file
Stringfilename="Comparison for .NET.pdf";StringinputPdfPath="C:\\input\\"+filename;//1. Create Editor instance - we do not use PdfLoadOptions here
Editoreditor=newEditor(inputPdfPath);//2. Edit PDF document with default PdfEditOptions - no need to create and pass PdfEditOptions explicitly
EditableDocumentoriginalDoc=editor.edit();//3. Generate HTML/CSS/resources, send to WYSIWYG-editor, edit there, send back to server and create EditableDocument... omitted here
EditableDocumenteditedDoc=originalDoc;//just use the same in the sake of simplicity
//4. Prepare PDF save options:
//4.1. Create instance
PdfSaveOptionssaveOptionsAdjusted=newPdfSaveOptions();//4.2. Adjust properties
saveOptionsAdjusted.setPassword("some_password");//protect output PDF with password
saveOptionsAdjusted.setFontEmbedding(FontEmbeddingOptions.EmbedAll);//set font embedding - all used
saveOptionsAdjusted.setCompliance(PdfCompliance.Pdf20);//set a PDF 2.0 (ISO 32000-2) standard compliance
saveOptionsAdjusted.setOptimizeMemoryUsage(true);//set memory optimization on
//5. Create an output stream and save to it
ByteArrayOutputStreamoutputStream=newByteArrayOutputStream();try{editor.save(editedDoc,outputStream,saveOptionsAdjusted);}finally{outputStream.close();}//6. Create another, default at this time, PDF save options
PdfSaveOptionssaveOptionsDefault=newPdfSaveOptions();//7. Save to the file path at this time
StringoutputPdfPath="C:\\output\\"+filename;editor.save(editedDoc,outputPdfPath,saveOptionsDefault);//8. Don't forget to dispose all
originalDoc.dispose();editedDoc.dispose();editor.dispose();
In this example we’ve created two output PDF files with different PDF saving options from one source EditableDocument, and saved them to the two distinct storages (memory and disk).
Obtaining PDF document info
Article Extracting document metainfo describes the getDocumentInfo() method, that allows to detect the document format and extract its metadata without editing it. Actually, after adding PDF support to the GroupDocs.Editor, this mechanism also works with PDF documents.
isEncrypted property of a boolean type. For the password-encoded documents it returns true, and false otherwise. For XPS files it always returns false, because the XPS format doesn’t support encryption.
As usual, if the input PDF, loaded into the Editor class, is encoded, then its correct password should be specified in the getDocumentInfo() method. If PDF is not encoded, then the value of the getDocumentInfo() is ignored.
The code example below demonstrates the extracting metadata from two PDFs: first one is unprotected, while second - protected.
importcom.groupdocs.editor.Editor;importcom.groupdocs.editor.formats.FixedLayoutFormats;importcom.groupdocs.editor.metadata.IDocumentInfo;importcom.groupdocs.editor.metadata.FixedLayoutDocumentInfo;//0. Prepare path to your input unprotected and protected PDF files
StringfilenameUnprotected="Comparison for .NET.pdf";StringfilenameProtected="NET_Framework-protected.pdf";StringinputPdfUnprotectedPath="C:\\input\\"+filenameUnprotected;StringinputPdfProtectedPath="C:\\input\\"+filenameProtected;//1. Create two Editor instances - we do not use PdfLoadOptions here
EditoreditorUnprotected=newEditor(inputPdfUnprotectedPath);EditoreditorProtected=newEditor(inputPdfProtectedPath);//2. Extract metadata: do not specify a password (null value instead) for the 1st, and DO specify for the 2nd
IDocumentInfounprotectedPdfInfo=editorUnprotected.getDocumentInfo(null);IDocumentInfoprotectedPdfInfo=editorProtected.getDocumentInfo("password");//3. Cast it if necessary and check properties
FixedLayoutDocumentInfocastedUnprotected=(FixedLayoutDocumentInfo)unprotectedPdfInfo;System.out.println(castedUnprotected.getPageCount());// e.g. 4
System.out.println(castedUnprotected.isEncrypted());// false
System.out.println(castedUnprotected.getSize());// e.g. file size in bytes
System.out.println(castedUnprotected.getFormat());// FixedLayoutFormats.Pdf
System.out.println(protectedPdfInfo.getPageCount());// e.g. 14
System.out.println(protectedPdfInfo.isEncrypted());// true
System.out.println(protectedPdfInfo.getSize());// e.g. file size in bytes
System.out.println(protectedPdfInfo.getFormat());// FixedLayoutFormats.Pdf
editorUnprotected.dispose();editorProtected.dispose();
Extended info
Pagination when saving
The backward converter, which generates the output PDF from EditableDocument, automatically detects the content in the obtained EditableDocument — if it was generated with the enablePagination flag set to true in PdfEditOptions, then pagination will be applied to the output PDF, and same for the false value. There is no separate pagination flag in PdfSaveOptions — the save stage follows the mode that was used during editing.
Different output formats
Keep in mind that, when input PDF was edited and you’re going to save it, it is not necessary to save it exactly in the PDF format — you are free to choose any compatible format, like all WordProcessing formats, or text format, or eBook format.
Code example below shows editing a PDF file and then saving the edited content to three different files in different formats.
importcom.groupdocs.editor.Editor;importcom.groupdocs.editor.EditableDocument;importcom.groupdocs.editor.formats.WordProcessingFormats;importcom.groupdocs.editor.options.PdfSaveOptions;importcom.groupdocs.editor.options.PdfCompliance;importcom.groupdocs.editor.options.WordProcessingSaveOptions;importcom.groupdocs.editor.options.TextSaveOptions;importjava.io.ByteArrayOutputStream;//0. Prepare path to your input PDF file
Stringfilename="Comparison for .NET.pdf";StringinputPdfPath="C:\\input\\"+filename;//1. Create Editor instance - we do not use PdfLoadOptions here
Editoreditor=newEditor(inputPdfPath);//2. Edit PDF document with default PdfEditOptions - no need to create and pass PdfEditOptions explicitly
EditableDocumentoriginalDoc=editor.edit();//3. Generate HTML/CSS/resources, send to WYSIWYG-editor, edit there, send back to server and create EditableDocument... omitted here
EditableDocumenteditedDoc=originalDoc;//just use the same in the sake of simplicity
//4. Prepare PDF save options
PdfSaveOptionspdfSaveOptions=newPdfSaveOptions();pdfSaveOptions.setCompliance(PdfCompliance.PdfA2a);//5. Prepare DOCX save options
WordProcessingSaveOptionsdocxSaveOptions=newWordProcessingSaveOptions(WordProcessingFormats.Docx);//6. Prepare TXT save options
TextSaveOptionstxtSaveOptions=newTextSaveOptions();txtSaveOptions.setPreserveTableLayout(true);//7. Save to PDF format to the stream
ByteArrayOutputStreampdfStream=newByteArrayOutputStream();try{editor.save(editedDoc,pdfStream,pdfSaveOptions);}finally{pdfStream.close();}//8. Save to DOCX format to the stream
ByteArrayOutputStreamdocxStream=newByteArrayOutputStream();try{editor.save(editedDoc,docxStream,docxSaveOptions);}finally{docxStream.close();}//9. Save to TXT format to the stream
ByteArrayOutputStreamtxtStream=newByteArrayOutputStream();try{editor.save(editedDoc,txtStream,txtSaveOptions);}finally{txtStream.close();}//10. Dispose all resources
editedDoc.dispose();originalDoc.dispose();editor.dispose();
Was this page helpful?
Any additional feedback you'd like to share with us?
Please tell us how we can improve this page.
Thank you for your feedback!
We value your opinion. Your feedback will help us improve our documentation.
On this page
Analyzing your prompt, please hold on...
An error occurred while retrieving the results. Please refresh the page and try again.