生成zip文件,将多个PDF文件分组,使用servlet和iText 7。

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

generate zip file grouping multiple pdf, using servlet and itext 7

问题

以下是你提供的代码的翻译部分:

private void printMore(HttpServletRequest req, HttpServletResponse resp) throws SQLException {
    String masterPath = req.getServletContext().getRealPath("/assets/template/templateStatement.pdf");
    try (PdfReader reader = new PdfReader(masterPath);
         ZipOutputStream zipFile = new ZipOutputStream(resp.getOutputStream());
         PdfWriter writer = new PdfWriter(zipFile);
         PdfDocument pdf = new PdfDocument(reader, writer);
         Document doc = new Document(pdf)) {

        List<Student> studentList = getFactoryDAO().getStatementDAO().selectStudentHasBalance();
        for (Student student : studentList) {

            // 为学生生成PDF
            PdfPage page = pdf.getPage(1);
            PdfCanvas canvas = new PdfCanvas(page);

            FontProgram fontProgram = FontProgramFactory.createFont();
            PdfFont font = PdfFontFactory.createFont(fontProgram, "utf-8", true);
            canvas.setFontAndSize(font, 10);

            canvas.beginText();

            canvas.setTextMatrix(178, 650); // 学生编号
            canvas.showText(student.getS_Code());

            canvas.setTextMatrix(200, 610); // 生成日期
            canvas.showText(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));

            canvas.endText();

            float[] pointsWidth = {60f, 120f, 70f, 70f};
            Table table = new Table(pointsWidth);
            table.setMarginTop(280);
            table.setMarginLeft(70);
            table.setFont(font);
            table.setFontSize(10);
            table.setTextAlignment(TextAlignment.CENTER);
            // 表头
            table.addCell(new Cell().add("报名日期"));
            table.addCell(new Cell().add("姓名"));
            table.addCell(new Cell().add("费用"));
            table.addCell(new Cell().add("备注"));
            // 表格内容
            table.addCell(new Cell().add(student.getTxnDate()));
            table.addCell(new Cell().add(student.getS_FullName()));
            table.addCell(new Cell().add(student.getFees()));
            table.addCell(new Cell().add(student.getObservation()));

            doc.add(table);

            ZipEntry zipEntry = new ZipEntry(student.getS_Code() + "_" + student.getS_LName() + ".pdf");
            zipFile.putNextEntry(zipEntry);
            //zipFile.write(); 是否需要使用它?

        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    resp.setHeader("Content-disposition", "attachment; filename=test.zip");
    resp.setContentType("application/zip");
}

在代码中,我保留了你提供的注释和代码逻辑,只是将代码翻译成了中文。如果你有任何问题或需要进一步帮助,请随时提问。

英文:

I'm trying to put multiple generated pdf into a zip from servlet using itext7, I've managed to put one pdf in a zip file but not more. Here is the code:

private void printMore(HttpServletRequest req, HttpServletResponse resp) throws SQLException {
String masterPath = req.getServletContext().getRealPath(&quot;/assets/template/templateStatement.pdf&quot;);
try (PdfReader reader = new PdfReader(masterPath);
ZipOutputStream zipFile = new ZipOutputStream(resp.getOutputStream());
PdfWriter writer = new PdfWriter(zipFile);
PdfDocument pdf = new PdfDocument(reader, writer);
Document doc = new Document(pdf)) {
List&lt;Student&gt; studentList = getFactoryDAO().getStatementDAO().selectStudentHasBalance();
for (Student student : studentList){
// Generate PDF for the student
PdfPage page = pdf.getPage(1);
PdfCanvas canvas = new PdfCanvas(page);
FontProgram fontProgram = FontProgramFactory.createFont();
PdfFont font = PdfFontFactory.createFont(fontProgram, &quot;utf-8&quot;, true);
canvas.setFontAndSize(font, 10);
canvas.beginText();
canvas.setTextMatrix(178, 650); // student code
canvas.showText(student.getS_Code());
canvas.setTextMatrix(200, 610); // Date of Statement
canvas.showText(new SimpleDateFormat(&quot;yyyy-MM-dd&quot;).format(new Date()));
canvas.endText();
float[] pointsWidth = {60f,120f,70f,70f};
Table table = new Table(pointsWidth);
table.setMarginTop(280);
table.setMarginLeft(70);
table.setFont(font);
table.setFontSize(10);
table.setTextAlignment(TextAlignment.CENTER);
//Header Table
table.addCell(new Cell().add(&quot;Date Inscription&quot;));
table.addCell(new Cell().add(&quot;Name&quot;));
table.addCell(new Cell().add(&quot;Fees&quot;));
table.addCell(new Cell().add(&quot;Observation&quot;));
//Detail Table
table.addCell(new Cell().add(student.getTxnDate()));
table.addCell(new Cell().add(student.getS_FullName));
table.addCell(new Cell().add(student.getFees));
table.addCell(new Cell().add(student.getObservation));
doc.add(table);
ZipEntry zipEntry = new ZipEntry(student.getS_Code() + &quot;_&quot; + student.getS_LName() + &quot;.pdf&quot;);
zipFile.putNextEntry(zipEntry);
//zipFile.write(); Shall I use it?
}
} catch (IOException e) {
e.printStackTrace();
}
resp.setHeader(&quot;Content-disposition&quot;,&quot;attachement; filename=test.zip&quot;);
resp.setContentType(&quot;application/zip&quot;);
}

I've based on this this post and this post but doesn't work. I already check more post like this but the version of itext7 has no PdfWriter.getInstance as mentionned. I've tried more thing but can't managed to go furthermore.

UPDATED :

After Enterman suggestion i updated it like this :

String masterPath = req.getServletContext().getRealPath(&quot;/assets/template/templateStatement.pdf&quot;);
try (PdfReader reader = new PdfReader(masterPath);
ZipOutputStream zipFile = new ZipOutputStream(resp.getOutputStream());
PdfWriter writer = new PdfWriter(zipFile);
PdfDocument pdf = new PdfDocument(reader, writer)
) {
List&lt;Student&gt; studentList = getFactoryDAO().getStatementDAO().selectStudentHasBalance();
for (Student student : studentList){
try (Document doc = new Document(pdf)){
// Generate PDF for the student
PdfPage page = pdf.getPage(1);
PdfCanvas canvas = new PdfCanvas(page);
FontProgram fontProgram = FontProgramFactory.createFont();
PdfFont font = PdfFontFactory.createFont(fontProgram, &quot;utf-8&quot;, true);
canvas.setFontAndSize(font, 10);
canvas.beginText();
canvas.setTextMatrix(178, 650); // student code
canvas.showText(student.getS_Code());
canvas.setTextMatrix(200, 610); // Date of Statement
canvas.showText(new SimpleDateFormat(&quot;yyyy-MM-dd&quot;).format(new Date()));
canvas.endText();
float[] pointsWidth = {60f,120f,70f,70f};
Table table = new Table(pointsWidth);
table.setMarginTop(280);
table.setMarginLeft(70);
table.setFont(font);
table.setFontSize(10);
table.setTextAlignment(TextAlignment.CENTER);
//Header Table
table.addCell(new Cell().add(&quot;Date Inscription&quot;));
table.addCell(new Cell().add(&quot;Name&quot;));
table.addCell(new Cell().add(&quot;Fees&quot;));
table.addCell(new Cell().add(&quot;Observation&quot;));
//Detail Table
table.addCell(new Cell().add(student.getTxnDate()));
table.addCell(new Cell().add(student.getS_FullName));
table.addCell(new Cell().add(student.getFees));
table.addCell(new Cell().add(student.getObservation));
doc.add(table);
ZipEntry zipEntry = new ZipEntry(student.getS_Code() + &quot;_&quot; + student.getS_LName() + &quot;.pdf&quot;);
zipFile.putNextEntry(zipEntry);
//zipFile.write(); Shall I use it?
}
}
} catch (IOException e) {
e.printStackTrace();
}
resp.setHeader(&quot;Content-disposition&quot;,&quot;attachement; filename=test.zip&quot;);
resp.setContentType(&quot;application/zip&quot;);

But still no luck.

Your help is welcome.

答案1

得分: 1

你应该尝试使用FileInputStream,就像下面这样(我自己的代码,在生产环境中运行良好)

private File createZip(List<File> forZip, LocalDate date) {

    String zipName = Constants.ORDER_FILE_PATH + date.getYear() + "-" + date.getMonth().getValue() + "-" + date.getMonth().getDisplayName(TextStyle.FULL, Locale.FRENCH) + ".zip";

    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(zipName);
        ZipOutputStream zipOut = new ZipOutputStream(fos);
        for (File srcFile : forZip) {
            FileInputStream fis = new FileInputStream(srcFile);
            ZipEntry zipEntry = new ZipEntry(srcFile.getName());
            zipOut.putNextEntry(zipEntry);

            byte[] bytes = new byte[1024];
            int length;
            while((length = fis.read(bytes)) >= 0) {
                zipOut.write(bytes, 0, length);
            }
            fis.close();
            //srcFile.delete();
        }
        zipOut.close();
        fos.close();
    } catch (IOException e) {
        logger.error("createZip", e);
    }

    return new File(zipName);
}
英文:

You should try using a FileInputStream, like below (code of my own, working well in production)

private File createZip(List&lt;File&gt; forZip, LocalDate date) {
String zipName = Constants.ORDER_FILE_PATH + date.getYear() +&quot;-&quot; + date.getMonth().getValue() + &quot;-&quot; + date.getMonth().getDisplayName(TextStyle.FULL, Locale.FRENCH) + &quot;.zip&quot;;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(zipName);
ZipOutputStream zipOut = new ZipOutputStream(fos);
for (File srcFile : forZip) {
FileInputStream fis = new FileInputStream(srcFile);
ZipEntry zipEntry = new ZipEntry(srcFile.getName());
zipOut.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while((length = fis.read(bytes)) &gt;= 0) {
zipOut.write(bytes, 0, length);
}
fis.close();
//srcFile.delete();
}
zipOut.close();
fos.close();
} catch (IOException e) {
logger.error(&quot;createZip&quot;, e);
}
return new File(zipName);
}

答案2

得分: 0

特别感谢BenjaminD和Enterman的支持,以及所有的堆栈社区。

我发布这个答案是为了那些遇到和我一样问题的人。(我被困了4天)。"使用itext 7和servlet生成多个PDF"

正如Enterman所说:"需要新的Document实例"。此外还需要PdfDocument。还有根据BenjaminD的指示:"首先生成PDF文件,然后将它们放入一个zip文件中"。

String masterPath = req.getServletContext().getRealPath("/assets/template/templateStatement.pdf");
try (ZipOutputStream zipOut = new ZipOutputStream(resp.getOutputStream())) {

    List<File> listFile = new ArrayList<>();
    List<Student> studentList = getFactoryDAO().getStatementDAO().selectStudentHasBalance();
    for (Student student : studentList) {
        
        File file = new File(student.getS_Code() + "_" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".pdf");
        try (PdfDocument pdf = new PdfDocument(new PdfReader(masterPath), new PdfWriter(file.getName()));
             Document doc = new Document(pdf)) {
               // 为学生生成PDF

            PdfPage page = pdf.getPage(1);
            PdfCanvas canvas = new PdfCanvas(page);

            FontProgram fontProgram = FontProgramFactory.createFont();
            PdfFont font = PdfFontFactory.createFont(fontProgram, "utf-8", true);
            canvas.setFontAndSize(font, 10);

            canvas.beginText();

            canvas.setTextMatrix(178, 650); // 学生代码
            canvas.showText(student.getS_Code());

            canvas.setTextMatrix(200, 610); // 对账单日期
            canvas.showText(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));

            canvas.endText();

            float[] pointsWidth = {60f, 120f, 70f, 70f};
            Table table = new Table(pointsWidth);
            table.setMarginTop(280);
            table.setMarginLeft(70);
            table.setFont(font);
            table.setFontSize(10);
            table.setTextAlignment(TextAlignment.CENTER);
            // 表头
            table.addCell(new Cell().add("Date Inscription"));
            table.addCell(new Cell().add("Name"));
            table.addCell(new Cell().add("Fees"));
            table.addCell(new Cell().add("Observation"));
            // 表格内容
            table.addCell(new Cell().add(student.getTxnDate()));
            table.addCell(new Cell().add(student.getS_FullName));
            table.addCell(new Cell().add(student.getFees));
            table.addCell(new Cell().add(student.getObservation));

            doc.add(table);

            listFile.add(file);
        }
    }
    
    File zipFile = createZip(listFile, new SimpleDateFormat("yyyy-MM-dd").format(new Date())); // BenjaminD的回答中的源代码

    ZipEntry zipEntry = new ZipEntry(zipFile.getName());
    zipOut.putNextEntry(zipEntry);
    FileInputStream fis = new FileInputStream(zipFile);
    byte[] bytes = new byte[1024];
    int length;
    while ((length = fis.read(bytes)) >= 0) {
        zipOut.write(bytes, 0, length);
    }
    fis.close();

    resp.setHeader("Content-disposition", "attachement; filename=" + zipFile);
    resp.setContentType("application/zip");

} catch (IOException e) {
    e.printStackTrace();
}

它将把zip文件放入另一个zip文件中(可以直接使用FileOutputStream,而不必再次放入zip文件中)。

再次感谢。

英文:

Special thanks for BenjaminD, Enterman for their support and all stack community.

I post this answer for those who has faced the same problem as me. (I've been stuck for 4 days). "Generating multiple PDF with itext 7 and servlets"

As Enterman said : "need new Instance of Document". In addition need PdfDocument also. And as BenjaminD instruction : "Generate a file PDF first, after put them into a zip".

String masterPath = req.getServletContext().getRealPath(&quot;/assets/template/templateStatement.pdf&quot;);
try (ZipOutputStream zipOut = new ZipOutputStream(resp.getOutputStream())) {
Liste&lt;File&gt; listFile = new ArrayList&lt;&gt;();
List&lt;Student&gt; studentList = getFactoryDAO().getStatementDAO().selectStudentHasBalance();
for (Student student : studentList){
File file = new File(student.getS_Code()+&quot;_&quot;+new SimpleDateFormat(&quot;yyyy-MM-dd&quot;).format(new Date())+&quot;.pdf&quot;);
try (PdfDocument pdf = new PdfDocument(new PdfReader(masterPath), new PdfWriter(file.getName()))
Document doc = new Document(pdf)){
// Generate PDF for the student
PdfPage page = pdf.getPage(1);
PdfCanvas canvas = new PdfCanvas(page);
FontProgram fontProgram = FontProgramFactory.createFont();
PdfFont font = PdfFontFactory.createFont(fontProgram, &quot;utf-8&quot;, true);
canvas.setFontAndSize(font, 10);
canvas.beginText();
canvas.setTextMatrix(178, 650); // student code
canvas.showText(student.getS_Code());
canvas.setTextMatrix(200, 610); // Date of Statement
canvas.showText(new SimpleDateFormat(&quot;yyyy-MM-dd&quot;).format(new Date()));
canvas.endText();
float[] pointsWidth = {60f,120f,70f,70f};
Table table = new Table(pointsWidth);
table.setMarginTop(280);
table.setMarginLeft(70);
table.setFont(font);
table.setFontSize(10);
table.setTextAlignment(TextAlignment.CENTER);
//Header Table
table.addCell(new Cell().add(&quot;Date Inscription&quot;));
table.addCell(new Cell().add(&quot;Name&quot;));
table.addCell(new Cell().add(&quot;Fees&quot;));
table.addCell(new Cell().add(&quot;Observation&quot;));
//Detail Table
table.addCell(new Cell().add(student.getTxnDate()));
table.addCell(new Cell().add(student.getS_FullName));
table.addCell(new Cell().add(student.getFees));
table.addCell(new Cell().add(student.getObservation));
doc.add(table);
listFile.add(file);
}
}
File zipFile = createZip(listFile, 
newSimpleDateFormat(&quot;yyyy-MM-dd&quot;).format(new Date())); //BenjaminD source in answer
ZipEntry zipEntry = new ZipEntry(zipFile.getName);
zipEntry.putNextEntry(zipEntry);
fileInputStream fis = new FileInputStream(zipFile);
byte[] bytes = new byte[1024];
int length;
while((length = fis.read(bytes)) &gt;= 0) {
zipOut.write(bytes, 0, length);
}
fis.close();
resp.setHeader(&quot;Content-disposition&quot;,&quot;attachement; filename=&quot; + zipFile);
resp.setContentType(&quot;application/zip&quot;);
} catch (IOException e) {
e.printStackTrace();
}     

It will put the zip in a zip (can Directly use FileOutpuStream to not put it again in a zip).

Thank you again.

huangapple
  • 本文由 发表于 2020年8月22日 21:49:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/63536903.html
匿名

发表评论

匿名网友

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

确定