gpt4 book ai didi

java - 如何向客户端返回iText PDF文档

转载 作者:行者123 更新时间:2023-12-02 03:18:57 25 4
gpt4 key购买 nike

我试图将 iText 生成的 PDF 从服务器端返回到客户端,以便用户能够存储它。我正在关注How to convert iTextPDF Document to Byte Array (AceFunk)

private static ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

public static byte[] main(java.util.List<Transcript> listymAwards, String scoutName, String groupName) {
Document document = new Document(PageSize.A4, 0f, 0f, 0f, 0f);

try {

//PdfWriter.getInstance(document, new FileOutputStream(FILE));
PdfWriter.getInstance(document, byteArrayOutputStream); // Do this BEFORE document.open()

document.open();
addMetaData(document);
addImages(document);
addTitlePage(document, scoutName);

//Add the table of achievements
if (listymAwards == null || listymAwards.isEmpty()) {
//Nothing to do.
//System.out.println("Scout not found.");
}else{

Paragraph preface = new Paragraph();

PdfPTable table = new PdfPTable(3);
table.setWidths(new int[]{1, 3, 1});
table.setHeaderRows(1);

PdfPCell c1 = new PdfPCell(new Phrase("Section"));
c1.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(c1);

c1 = new PdfPCell(new Phrase("Award"));
c1.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(c1);

c1 = new PdfPCell(new Phrase("Date"));
c1.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(c1);
table.setHeaderRows(1);

String storedName = null;
int noRows = 0;
String firstTable = "Yes";
DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
DateFormat df2 = new SimpleDateFormat("dd-MM-yyyy");
// We add three empty lines
addEmptyLine(preface, 1);
addEmptyLine(preface, 1);
addEmptyLine(preface, 1);

for (final Transcript scoutNamesDescription : listymAwards) {
if (firstTable.equals("Yes") && noRows > 30){ // Change this to number of rows required
noRows = 0;
firstTable = "No";
document.add(table);
document.newPage();
table.flushContent();
}else{
if (firstTable.equals("No") && noRows > 50){ // Change this to number of rows required
// We add three empty lines if not the first table
document.add(preface);
}
}

noRows++;

if (scoutNamesDescription.getSection().equals(storedName)){
table.addCell(" ");
}else{
storedName = scoutNamesDescription.getSection();
table.addCell(scoutNamesDescription.getSection());
}
table.addCell(scoutNamesDescription.getAwardName());

Date awardedDate = df1.parse(scoutNamesDescription.getAwardedDate());
String awardedString = df2.format(awardedDate);
table.addCell(awardedString);
}
//Print the remaining rows.
// We add three empty lines if not the first table
if (firstTable.equals("No")){
document.add(preface);
}else{
firstTable = "No";
}
document.add(table);
}

//Add signature
addSignaturePage(document, groupName);

document.close();


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

byte[] pdfBytes = byteArrayOutputStream.toByteArray();
return pdfBytes;

}

返回到服务器端:

    byte[] pdfBytes = ScoutTranscript.main(listymAwards, scoutName, groupName);
System.out.println("Point 3");

return pdfBytes;

然后返回到客户端:

Window.open("data:application/pdf;base64,"+result,"_parent", "location=no");

我在哪里收到错误消息:

This site can’t be reached

The webpage at data:application/pdf;base64,[B@154 might be temporarily down or it may have moved permanently to a new web address.

最佳答案

错误#1:

让我们从一个不以任何方式涉及 iText 的小测试开始。试试这个:

byte[] test = "Test".getBytes();
System.out.println("Test " + test);

输出中写入了什么?就我而言,它是:

Test [B@3da3da69

[ 表示我正在尝试将数组转换为 StringB 表示数组包含字节; @ 将类型与 ID 分开;后面的字符是十六进制格式的 ID(哈希码)。请参阅 Java: Syntax and meaning behind "[B@1ef9157"? Binary/Address?

如果 result 的类型为 byte[] 并且您有以下行:

Window.open("data:application/pdf;base64,"+result,"_parent", "location=no");

然后 "data:application/pdf;base64,"+result 会产生类似 "data:application/pdf;base64,[B@154" 的结果。这没有任何意义,不是吗?

现在试试这个:

byte[] test = "Test".getBytes();
System.out.println("Test " + new String(test));

输出为:

Test Test

您使用的是byte[],就好像它是String。这是您的第一个错误。

我本来想说一些难听的话,因为这不是 Java 开发人员会犯的错误。然而,我刚刚读了你的简历,我发现你是 Java 新手,并且你(可能)正在自学如何用 Java 编写代码(就像我 20 年前所做的那样),所以我对自己进行了审查;-)

错误#2:

您无法通过替换代码来解决您的问题:

Window.open("data:application/pdf;base64,"+ new String(result),"_parent", "location=no");

您不能这样做,因为您犯了第二个错误:result 中的字节表示二进制文件,并且浏览器中的 JavaScript 需要 Base64 编码文件。 Base64 编码用于将二进制转换为文本,反之亦然。请参阅 What is base 64 encoding used for?

如果您想将二进制 PDF 文件作为 Base64 编码字符串发送到浏览器,则必须对字节进行 Base64 编码。这可以通过此类来完成:http://itextsupport.com/apidocs/itext5/latest/com/itextpdf/text/pdf/codec/Base64.html

例如:

Window.open("data:application/pdf;base64,"+ Base64.encodeBytes(result),"_parent", "location=no");

这应该已经适用于某些浏览器,但不适用于所有浏览器。我不知道你在哪里使用 Window.open() ,也不知道你为什么要涉及 Base64。您可能想详细说明这一点。在我看来,这是一个坏主意。

应该如何完成:

通常,您将编写一个在应用程序服务器中运行的 Servlet。可以使用 URL 从浏览器访问该 servlet。 您不需要按照其他答案中的建议将生成的文件保存在服务器上(我否决了该答案,因为它没有帮助并且完全错误)。您创建 ByteArrayOutputStream 然后获取 byte[] 的方法是正确的,但您必须将这些字节提供给 HttpServletResponse 对象。

请参阅 How can I serve a PDF to a browser without storing a file on the server side? 了解完整示例。

关于 Window.open()

您可以在客户端使用Window.open(),在新窗口中打开网页。例如:

window.open("http://www.itextpdf.com");

您可以提供包含此代码段的页面,但在您的情况下,您必须将 http://www.itextpdf.com 替换为为您的 servlet 定义的 URL。

您可能在这里找到了您的“解决方案”:Opening PDF String in new window with javascript

但是如果您阅读评论,您会发现这种方法在与某些浏览器结合使用时会出现问题。

关于java - 如何向客户端返回iText PDF文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39885410/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com