如何获取 iText 7 中 PDF 文档的页面大小

huangapple go评论69阅读模式
英文:

How to get page size of pdf document iText 7

问题

import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Text;
import com.itextpdf.kernel.colors.Color;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;

import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.Locale;

import org.json.JSONArray;
import org.json.JSONObject;

public class PDFGenerator {
    public static final String DESTINATION = "path/exampleSMA.pdf";

    public static void main(String[] args) throws Exception {
        String clientData = /*... JSON data ...*/;

        new PDFGenerator().createPdf(DESTINATION, clientData);
    }

    public void createPdf(String dest, String data) throws IOException {
        /*... JSON data processing ...*/

        PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
        try (Document document = new Document(pdf)) {
            document.setMargins(120, 36, 120, 36);
            
            // ... Additional code for creating PDF content ...
            
            for (int i = 1; i <= document.getPdfDocument().getNumberOfPages(); i++) {
                try {
                    Rectangle pageSize = document.getPdfDocument().getPage(i).getPageSize();
                    System.out.println("PAGINA DEL PDF" + i);
                    System.out.println("RECTANGLE....." + pageSize);
                } catch (Exception e) {
                    System.out.println("EXCEPCION RECTANGULO..." + e);
                }
            }
        }
    }
}

Please note that the code provided is just a portion of the original code and has been cleaned up for clarity. It includes the main structure of the PDF generation process using the iText library, but some parts related to JSON data processing, image paths, font paths, and other potential details are missing. Make sure to integrate this code properly into your original project, considering these aspects.

英文:

I have a java program in iText 7 that receive JSON data and generate a PDF document (with header and footer) that works fine with data in variable clientData in comment, but when use the variable in no comments clientData doesn't works, i'm getting this error java.lang.NullPointerException, the error appears when build the header and footer (in this line Rectangle pageSize = document.getPdfDocument().getPage(i).getPageSize();), but don't know what data is null, because the JSON data and the structure of the PDF is the same, what am i doing wrong?

This is all the code:

import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.extgstate.PdfExtGState;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.element.Text;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.Color;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.List;
import com.itextpdf.layout.element.ListItem;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment;
import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.Locale;
import org.json.JSONArray;
import org.json.JSONObject;
public class PDFGenerator {
public static final String DESTINATION = &quot;path/exampleSMA.pdf&quot;;
public static void main(String[] args) throws Exception {
File file = new File(DEST);
file.getParentFile().mkdirs();
//WORK
//String clientData = &quot;&#39;{\&quot;nombre_cliente\&quot;:\&quot;Postobon\&quot;,\&quot;contacto\&quot;:\&quot;Kelly Paz\&quot;,\&quot;email\&quot;:\&quot;ventas@test.com\&quot;,\&quot;telefono\&quot;:\&quot;233774983\&quot;,\&quot;observaciones\&quot;:\&quot;\&quot;,\&quot;totalizar\&quot;:true,\&quot;mostrar_impuesto\&quot;:false,\&quot;credito\&quot;:true,\&quot;creador\&quot;:\&quot;jplata\&quot;,\&quot;creador_nombre\&quot;:\&quot;JAIME ANTONIO\&quot;,\&quot;creador_apellido\&quot;:\&quot;PLATA BOGOYA\&quot;,\&quot;cargo_asesor\&quot;:\&quot;GERENTE\&quot;,\&quot;email_asesor\&quot;:\&quot;dyehuty@gmail.com\&quot;,\&quot;productos\&quot;:[{\&quot;modelo\&quot;:\&quot;BOLSA ACCESORIOS ESTANDAR\&quot;,\&quot;tela\&quot;:\&quot;KAMBREL O POLITEX DE 70GR\&quot;,\&quot;cantidad\&quot;:\&quot;3000\&quot;,\&quot;destino\&quot;:186,\&quot;destino_label\&quot;:\&quot;CALDAS - NEIRA\&quot;,\&quot;ancho\&quot;:22,\&quot;alto\&quot;:33,\&quot;fuelle\&quot;:0,\&quot;manija\&quot;:0,\&quot;estampado_cara_frontal\&quot;:\&quot;1 TINTA MATE\&quot;,\&quot;estampado_cara_posterior\&quot;:\&quot;2 TINTAS MATE\&quot;,\&quot;valor_bolsa\&quot;:\&quot;1605\&quot;,\&quot;valor_iva\&quot;:\&quot;304\&quot;,\&quot;iva\&quot;:19,\&quot;accesorios_modelo\&quot;:[{\&quot;id\&quot;:\&quot;1\&quot;,\&quot;nombre\&quot;:\&quot;CORDON ESTANDAR SENCILLO; PARA BOLSAS CIERRE CORDON O BOLERO.\&quot;,\&quot;ancho\&quot;:0,\&quot;alto\&quot;:0}],\&quot;accesorios_adicionales\&quot;:[{\&quot;id\&quot;:\&quot;37\&quot;,\&quot;nombre\&quot;:\&quot;ESTE ACCESORIO SE USA PARA COLOCARLE BASE DE CARTON FORRADA EN EL MISMO MATERIAL A LA BOLSA. NORMALMENTE SE USA PARA LA BOLSA ANCHETA; PERO SE LE PUEDE COLOCAR A CUALQUIER BOLSA.\&quot;,\&quot;ancho\&quot;:0,\&quot;alto\&quot;:0},{\&quot;id\&quot;:\&quot;23\&quot;,\&quot;nombre\&quot;:\&quot;BOLSILLO EN EL MISMO MATERIAL DE LA BOLSA; SE USA PARA LA BOLSA AUTOGUARDABLE TIPO BILLETERA; O PARA CUALQUIER BOLSA QUE SE DESEE LLEVE UN BOLSILLO.  EN LOS CAMPOS ALTO Y ANCHO; INDIQUE LAS DIMENSIONES DE &#201;STE BOLSILLO.\&quot;,\&quot;ancho\&quot;:20,\&quot;alto\&quot;:20},{\&quot;id\&quot;:\&quot;36\&quot;,\&quot;nombre\&quot;:\&quot;ESTE ACCESORIO ES UNA CAPA QUE SE COLOCA ENCIMA DEL CUBREVESTIDO. EN EL CAMPO ALTO: INDIQUE EL ALTO DE LA CAPERUZA.\&quot;,\&quot;ancho\&quot;:0,\&quot;alto\&quot;:22}],\&quot;cantidadesReporte\&quot;:[{\&quot;cantidad\&quot;:3000,\&quot;valor_bolsa\&quot;:1605,\&quot;valor_iva\&quot;:0,\&quot;subtotal\&quot;:4815000,\&quot;total\&quot;:4815000}]}]}&#39;&quot;;
//NOT WORK
String clientData = &quot;&#39;{\&quot;nombre_cliente\&quot;:\&quot;MARCA DE PRUEBA\&quot;,\&quot;contacto\&quot;:\&quot;Harry\&quot;,\&quot;email\&quot;:\&quot;harry@test.com\&quot;,\&quot;telefono\&quot;:\&quot;4553773773\&quot;,\&quot;observaciones\&quot;:\&quot;\&quot;,\&quot;totalizar\&quot;:false,\&quot;mostrar_impuesto\&quot;:true,\&quot;credito\&quot;:false,\&quot;creador\&quot;:\&quot;jvalderrama\&quot;,\&quot;creador_nombre\&quot;:\&quot;JUAN CARLOS\&quot;,\&quot;creador_apellido\&quot;:\&quot;VALDERRAMA GONZALEZ\&quot;,\&quot;cargo_asesor\&quot;:\&quot;desarrollador\&quot;,\&quot;email_asesor\&quot;:\&quot;dyehuty@gmail.com\&quot;,\&quot;telefono_asesor\&quot;:\&quot;2373719 EXT 1147 - 5138731 - 8033205\&quot;,\&quot;celular_asesor\&quot;:\&quot;3149008989\&quot;,\&quot;productos\&quot;:[{\&quot;modelo\&quot;:\&quot;BOLSA ACCESORIOS CIERRE ESPECIAL\&quot;,\&quot;tela\&quot;:\&quot;KAMBREL O POLITEX DE 70GR\&quot;,\&quot;cantidad\&quot;:\&quot;300,600,1000\&quot;,\&quot;destino\&quot;:4,\&quot;destino_label\&quot;:\&quot;ANTIOQUIA - BARBOSA\&quot;,\&quot;ancho\&quot;:23,\&quot;alto\&quot;:44,\&quot;fuelle\&quot;:0,\&quot;manija\&quot;:0,\&quot;estampado_cara_frontal\&quot;:\&quot;1 TINTA MATE\&quot;,\&quot;estampado_cara_posterior\&quot;:\&quot;SIN ESTAMPADO\&quot;,\&quot;estampado_fuelle_izquierdo\&quot;:\&quot;SIN ESTAMPADO\&quot;,\&quot;estampado_fuelle_derecho\&quot;:\&quot;SIN ESTAMPADO\&quot;,\&quot;estampado_fuelle_base\&quot;:\&quot;SIN ESTAMPADO\&quot;,\&quot;valor_bolsa\&quot;:\&quot;1543,1202,1151\&quot;,\&quot;valor_iva\&quot;:\&quot;293,228,218\&quot;,\&quot;iva\&quot;:19,\&quot;accesorios_modelo\&quot;:[],\&quot;accesorios_adicionales\&quot;:[{\&quot;id\&quot;:\&quot;37\&quot;,\&quot;nombre\&quot;:\&quot;BASE DE CARTON FORRADO\&quot;,\&quot;descripcion\&quot;:\&quot;ESTE ACCESORIO SE USA PARA COLOCARLE BASE DE CARTON FORRADA EN EL MISMO MATERIAL A LA BOLSA. NORMALMENTE SE USA PARA LA BOLSA ANCHETA,PERO SE LE PUEDE COLOCAR A CUALQUIER BOLSA.\&quot;,\&quot;ancho\&quot;:2,\&quot;alto\&quot;:0}],\&quot;cantidadesReporte\&quot;:[{\&quot;cantidad\&quot;:300,\&quot;valor_bolsa\&quot;:1543,\&quot;valor_iva\&quot;:87900,\&quot;subtotal\&quot;:462900,\&quot;total\&quot;:550800},{\&quot;cantidad\&quot;:600,\&quot;valor_bolsa\&quot;:1202,\&quot;valor_iva\&quot;:136800,\&quot;subtotal\&quot;:721200,\&quot;total\&quot;:858000},{\&quot;cantidad\&quot;:1000,\&quot;valor_bolsa\&quot;:1151,\&quot;valor_iva\&quot;:218000,\&quot;subtotal\&quot;:1151000,\&quot;total\&quot;:1369000}]},{\&quot;modelo\&quot;:\&quot;BOLSA ACCESORIOS CIERRE ESPECIAL\&quot;,\&quot;tela\&quot;:\&quot;YUTE LAMINADO COLOR CRUDO\&quot;,\&quot;cantidad\&quot;:\&quot;300,600,1000\&quot;,\&quot;destino\&quot;:4,\&quot;destino_label\&quot;:\&quot;ANTIOQUIA - BARBOSA\&quot;,\&quot;ancho\&quot;:23,\&quot;alto\&quot;:44,\&quot;fuelle\&quot;:0,\&quot;manija\&quot;:0,\&quot;estampado_cara_frontal\&quot;:\&quot;1 TINTA MATE\&quot;,\&quot;estampado_cara_posterior\&quot;:\&quot;SIN ESTAMPADO\&quot;,\&quot;estampado_fuelle_izquierdo\&quot;:\&quot;SIN ESTAMPADO\&quot;,\&quot;estampado_fuelle_derecho\&quot;:\&quot;SIN ESTAMPADO\&quot;,\&quot;estampado_fuelle_base\&quot;:\&quot;SIN ESTAMPADO\&quot;,\&quot;valor_bolsa\&quot;:\&quot;6439,5016,4830\&quot;,\&quot;valor_iva\&quot;:\&quot;1223,953,917\&quot;,\&quot;iva\&quot;:19,\&quot;accesorios_modelo\&quot;:[],\&quot;accesorios_adicionales\&quot;:[{\&quot;id\&quot;:\&quot;37\&quot;,\&quot;nombre\&quot;:\&quot;BASE DE CARTON FORRADO\&quot;,\&quot;descripcion\&quot;:\&quot;ESTE ACCESORIO SE USA PARA COLOCARLE BASE DE CARTON FORRADA EN EL MISMO MATERIAL A LA BOLSA. NORMALMENTE SE USA PARA LA BOLSA ANCHETA,PERO SE LE PUEDE COLOCAR A CUALQUIER BOLSA.\&quot;,\&quot;ancho\&quot;:2,\&quot;alto\&quot;:0}],\&quot;cantidadesReporte\&quot;:[{\&quot;cantidad\&quot;:300,\&quot;valor_bolsa\&quot;:6439,\&quot;valor_iva\&quot;:366900,\&quot;subtotal\&quot;:1931700,\&quot;total\&quot;:2298600},{\&quot;cantidad\&quot;:600,\&quot;valor_bolsa\&quot;:5016,\&quot;valor_iva\&quot;:571800,\&quot;subtotal\&quot;:3009600,\&quot;total\&quot;:3581400},{\&quot;cantidad\&quot;:1000,\&quot;valor_bolsa\&quot;:4830,\&quot;valor_iva\&quot;:917000,\&quot;subtotal\&quot;:4830000,\&quot;total\&quot;:5747000}]},{\&quot;modelo\&quot;:\&quot;BOLSA ACCESORIOS CIERRE ESPECIAL\&quot;,\&quot;tela\&quot;:\&quot;TELA DE SUBLIMAR EN KAMB. DE 70GR\&quot;,\&quot;cantidad\&quot;:\&quot;300,600,1000\&quot;,\&quot;destino\&quot;:4,\&quot;destino_label\&quot;:\&quot;ANTIOQUIA - BARBOSA\&quot;,\&quot;ancho\&quot;:23,\&quot;alto\&quot;:44,\&quot;fuelle\&quot;:0,\&quot;manija\&quot;:0,\&quot;estampado_cara_frontal\&quot;:\&quot;1 TINTA MATE\&quot;,\&quot;estampado_cara_posterior\&quot;:\&quot;SIN ESTAMPADO\&quot;,\&quot;estampado_fuelle_izquierdo\&quot;:\&quot;SIN ESTAMPADO\&quot;,\&quot;estampado_fuelle_derecho\&quot;:\&quot;SIN ESTAMPADO\&quot;,\&quot;estampado_fuelle_base\&quot;:\&quot;SIN ESTAMPADO\&quot;,\&quot;valor_bolsa\&quot;:\&quot;1906,1485,1423\&quot;,\&quot;valor_iva\&quot;:\&quot;362,282,270\&quot;,\&quot;iva\&quot;:19,\&quot;accesorios_modelo\&quot;:[],\&quot;accesorios_adicionales\&quot;:[{\&quot;id\&quot;:\&quot;37\&quot;,\&quot;nombre\&quot;:\&quot;BASE DE CARTON FORRADO\&quot;,\&quot;descripcion\&quot;:\&quot;ESTE ACCESORIO SE USA PARA COLOCARLE BASE DE CARTON FORRADA EN EL MISMO MATERIAL A LA BOLSA. NORMALMENTE SE USA PARA LA BOLSA ANCHETA,PERO SE LE PUEDE COLOCAR A CUALQUIER BOLSA.\&quot;,\&quot;ancho\&quot;:2,\&quot;alto\&quot;:0}],\&quot;cantidadesReporte\&quot;:[{\&quot;cantidad\&quot;:300,\&quot;valor_bolsa\&quot;:1906,\&quot;valor_iva\&quot;:108600,\&quot;subtotal\&quot;:571800,\&quot;total\&quot;:680400},{\&quot;cantidad\&quot;:600,\&quot;valor_bolsa\&quot;:1485,\&quot;valor_iva\&quot;:169200,\&quot;subtotal\&quot;:891000,\&quot;total\&quot;:1060200},{\&quot;cantidad\&quot;:1000,\&quot;valor_bolsa\&quot;:1423,\&quot;valor_iva\&quot;:270000,\&quot;subtotal\&quot;:1423000,\&quot;total\&quot;:1693000}]}]}&#39;&quot;;
new PDFGenerator().createPdf(DEST, clientData);		
}
public void createPdf(String dest, String data) throws IOException {
data = data.replace(&quot;&#39;&quot;,&quot;&quot;);
JSONObject jsonPeticion = new JSONObject(data);
JSONArray jsonProductos= jsonPeticion.getJSONArray(&quot;productos&quot;);
boolean mostrarIva = jsonPeticion.getBoolean(&quot;mostrar_impuesto&quot;);
NumberFormat formateador = NumberFormat.getInstance(new Locale(&quot;us&quot;, &quot;US&quot;));
formateador.setMinimumFractionDigits(0);
formateador.setMaximumFractionDigits(0);
System.out.println(&quot;JSON ARRAY......&quot; + jsonProductos);
System.out.println(&quot;JSON ARRAY LENGTH......&quot; + jsonProductos.length());
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
try (Document document = new Document(pdf)) {
document.setMargins(120, 36, 120, 36);
document.add(new Paragraph(&quot;ESPECIFICACIONES T&#201;CNICAS DEL PRODUCTO&quot;)
.setTextAlignment(TextAlignment.CENTER)
.setBold());
for (int i = 0; i &lt; jsonProductos.length(); i++) {
Text textoTinta = new Text(&quot;Tinta Utilizada&quot;);
textoTinta.setUnderline(1.5f, -1);
textoTinta.setTextAlignment(TextAlignment.LEFT);
Text textoTintaDescripcion = new Text(&quot;: Las tintas que usamos son 100% Ecol&#243;gicas y Base Agua, &quot;
+ &quot;nuestra visi&#243;n no es solo comercial sino de responsabilidad &quot;
+ &quot;con el medio ambiente y social.&quot;);
Text textoNota = new Text(&quot;NOTA: &quot;).setBold();
textoNota.setTextAlignment(TextAlignment.LEFT);
Text textoNotaDescripcion = new Text(&quot;Se&#241;or cliente por favor tener presente, que en el momento &quot;
+ &quot;de la facturaci&#243;n, debemos facturar todo lo que salga, normalmente &quot;
+ &quot;puede salir un 5% de m&#225;s o de menos.&quot;);
document.add(new Paragraph(textoTinta).add(textoTintaDescripcion)
.setTextAlignment(TextAlignment.JUSTIFIED));
document.add(new Paragraph(textoNota).add(textoNotaDescripcion)
.setTextAlignment(TextAlignment.JUSTIFIED));
String IMG = &quot;C:\\path\\images\\logoSmallBiobolsa.png&quot;;
String FONT = &quot;C:\\path\\COMIC.ttf&quot;;
ImageData imageData = ImageDataFactory.create(IMG);
Image pdfImg = new Image(imageData);
pdfImg.setWidth(70);
pdfImg.setHeight(77);
Color verdeBioBolsa = new DeviceRgb(5, 94, 27);
PdfFont comic = PdfFontFactory.createFont(FONT, true);
System.out.println(&quot;MARGENES SUPERIOR..... &quot; + document.getTopMargin());
System.out.println(&quot;MARGENES INFERIOR..... &quot; + document.getBottomMargin());
System.out.println(&quot;MARGENES IZQUIERDO..... &quot; + document.getLeftMargin());
System.out.println(&quot;MARGENES DERECHO..... &quot; + document.getRightMargin());
Paragraph headerImg = new Paragraph(&quot;&quot;).add(pdfImg);
Paragraph headerNombreEmpresa = new Paragraph(&quot;BIO BOLSA S.A.S&quot;)
.setFont(comic)
.setFontSize(20)
.setBold()
.setFontColor(verdeBioBolsa);
Paragraph headerSlogan = new Paragraph(&quot;!!Una Empresa con Conciencia Ambiental!!&quot;)
.setFont(comic)
.setFontSize(14)
.setFontColor(verdeBioBolsa);
Paragraph headerRegimen = new Paragraph(&quot;R&#233;gimen Com&#250;n&quot;)
.setFont(comic)
.setFontSize(12)
.setBold()
.setFontColor(verdeBioBolsa);
Paragraph headerIdentificador = new Paragraph(&quot;NIT: 900.390.537-1&quot;)
.setFont(comic)
.setFontSize(12)
.setFontColor(verdeBioBolsa);
Paragraph footerTelefonosAsesor = new Paragraph(&quot;Tels: (57) (1) 7137516 EXT 1142 – 7138731 - 2033205 Cel: (57) 300 275 45 51&quot;)
.setFontSize(10)
.setFontColor(verdeBioBolsa);
Paragraph footerWebEmail = new Paragraph(&quot;Web: www.biobolsa.com.co   E-mail: pchacon@biobolsa.com.co&quot;)
.setFontSize(10)
.setFontColor(verdeBioBolsa);
Paragraph footerDireccion = new Paragraph(&quot;F&#225;brica CRA 57 NO 45 A – 52 SUR LA SEVILLANA&quot;)
.setFontSize(10)
.setFontColor(verdeBioBolsa);
Paragraph footerCiudad = new Paragraph(&quot;Bogot&#225; D.C, Colombia&quot;)
.setFontSize(10)
.setFontColor(verdeBioBolsa);
for (int i = 1; i &lt;= document.getPdfDocument().getNumberOfPages(); i++) {
System.out.println(&quot;PAGINA DEL PDF&quot; + i);
try {
Rectangle pageSize = document.getPdfDocument().getPage(i).getPageSize();
//Rectangle pageSize = document.getPdfDocument().getPage(i).getMediaBox();
System.out.println(&quot;RECTANGLE.....&quot; + pageSize);
} catch (Exception e) {
// TODO: handle exception
System.out.println(&quot;EXCEPCION RECTANGULO...&quot; + e);
}
}
}
}
}

答案1

得分: 6

###In short

问题出在您的代码访问了iText已经刷新到目标文件中并释放出内存的页面。您可以通过使用三参数Document构造函数,并将immediateFlush参数设置为false来指示iText不要过早刷新页面,即将

try (Document document = new Document(pdf)) {

替换为

try (Document document = new Document(pdf, pdf.getDefaultPageSize(), false)) {

###Some explanations

iText的设计目标是在不需要相应巨大内存量的情况下生成大型PDF(或同时生成多个PDF)。它通过将PDF的已完成部分写入输出目标并将其从内存中移除来降低其内存占用。特别是在创建多页文档时,通常只有当前页和上一页保留在内存中,而之前的页面则会被刷新并且剩余页面对象的内容设置为null

因此,当您最终迭代遍历PDF的所有页面时,除了最近的页面外,其他页面的MediaBox条目实际上已经不存在了,因此在尝试访问页面大小时会出现NullPointerException

对于像您的用例这样不适合早期刷新的情况,iText提供了上面使用的标志,以防止它过早刷新页面。

###As an aside...

... 如果您想知道为什么您的问题没有早些被回答:您发布了一段庞大的代码,甚至无法执行以复现问题,因为您没有为data参数提供JSON字符串。为了能够重现问题,我不得不将您的代码削减到能够重现问题的关键核心部分:

public void createPdf(String dest) throws IOException {

    PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
    try (Document document = new Document(pdf)) {

        document.setMargins(120, 36, 120, 36);

        document.add(new Paragraph("some content"));
        document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
        document.add(new Paragraph("some more content"));
        document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
        document.add(new Paragraph("still more content"));

        for (int i = 1; i <= document.getPdfDocument().getNumberOfPages(); i++) {

            System.out.println("PAGINA DEL PDF" + i);
            try {
                Rectangle pageSize = document.getPdfDocument().getPage(i).getPageSize();
                // Rectangle pageSize = document.getPdfDocument().getPage(i).getMediaBox();
                System.out.println("RECTANGLE....." + pageSize);
            } catch (Exception e) {
                // TODO: handle exception
                System.out.println("EXCEPCION RECTANGULO..." + e);
            }
        }
    }
}

如果您自己这样做了,您的问题会更早得到解答。

英文:

###In short

The problem is due to your code accessing pages which iText already has flushed out of memory to the target file. You can instruct iText not to flush pages early by using the three-parameter Document constructor and setting the immediateFlush parameter to false, i.e. by replacing

try (Document document = new Document(pdf)) {

by

try (Document document = new Document(pdf, pdf.getDefaultPageSize(), false)) {

###Some explanations

iText is designed to be usable in contexts in which huge PDFs (or many PDFs concurrently) can be generated without requiring a correspondingly huge amount of memory. It lowers its memory footprint by writing finished parts of the PDF to its output target and removing them from memory. In particular when creating multi-page documents, usually only the current and the previous page remain in memory while pages before that are flushed and have the contents of the remaining page object set to null.

So when you eventually iterate over all the pages of your PDF, all but the most recent ones indeed don't have their MediaBox entries anymore, so you get a NullPointerException when trying to access the page size.

For use cases like yours in which early flushing is not appropriate, iText offers the flag used above to keep it from flushing pages early.

###As an aside...

... if you wonder why your question has not been answered earlier: You posted a gigantic piece of code which one couldn't even execute to reproduce the issue as you did not provide a JSON string for the data parameter. To be able to reproduce the issue, therefore, I had to cut down your code to the essential core that reproduces the issue:

public void createPdf(String dest) throws IOException {
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
try (Document document = new Document(pdf)) {
document.setMargins(120, 36, 120, 36);
document.add(new Paragraph(&quot;some content&quot;));
document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
document.add(new Paragraph(&quot;some more content&quot;));
document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
document.add(new Paragraph(&quot;still more content&quot;));
for (int i = 1; i &lt;= document.getPdfDocument().getNumberOfPages(); i++) {
System.out.println(&quot;PAGINA DEL PDF&quot; + i);
try {
Rectangle pageSize = document.getPdfDocument().getPage(i).getPageSize();
// Rectangle pageSize = document.getPdfDocument().getPage(i).getMediaBox();
System.out.println(&quot;RECTANGLE.....&quot; + pageSize);
} catch (Exception e) {
// TODO: handle exception
System.out.println(&quot;EXCEPCION RECTANGULO...&quot; + e);
}
}
}
}

If you had done so yourself, you would have had your question answered much earlier.

答案2

得分: 0

如果您使用 immediateFlush=false,请在操作文档后不要忘记使用 document.Flush()

Document document =  
new Document(pdf, pdf.GetDefaultPageSize(), false);
...
document.Flush();
pdf.Close();
英文:

If you use immediateFlush=false don't forget use document.Flush() after manipulate document

Document document =  
new Document(pdf, pdf.GetDefaultPageSize(), false);
...
document.Flush();
pdf.Close();

huangapple
  • 本文由 发表于 2020年3月16日 07:04:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/60698558.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定