英文:
Creating file with PDFBox and downloading it [SOLVED]
问题
我在这里看到了很多答案,我复制了一些例子并尝试应用它,但我不知道如何使这个工作起来。我正在尝试使用PDFBox创建一个文件,并使用响应发送它,以便用户可以下载它。到目前为止,我能够下载文件,但是文件是空白的。我已经尝试过只是加载计算机上的示例文件并使用PDFBox下载它,但效果是一样的,是空白的。我现在正在使用的代码是:
@GET
@Path("/dataPDF")
@Produces("application/pdf")
public Response retrievePDF(){
try {
ByteArrayOutputStream output = new ByteArrayOutputStream();
output = createPDF();
ResponseBuilder response = Response.ok(output.toByteArray(), "application/pdf");
response.header("Content-Disposition","attachment; filename=file.pdf");
return response.build();
}
catch (Exception ex) {
ex.printStackTrace();
return Response.status(Response.Status.NOT_FOUND).build();
}
}
public ByteArrayOutputStream createPDF() throws IOException {
PDFont font = PDType1Font.HELVETICA;
PDPageContentStream contentStream;
ByteArrayOutputStream output =new ByteArrayOutputStream();
PDDocument document =new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
contentStream = new PDPageContentStream(document, page);
contentStream.beginText();
contentStream.setFont(font, 20);
contentStream.newLineAtOffset(10, 770);
contentStream.showText("Amount: $1.00");
contentStream.endText();
contentStream.beginText();
contentStream.setFont(font, 20);
contentStream.newLineAtOffset(200, 880);
contentStream.showText("Sequence Number: 123456789");
contentStream.endText();
contentStream.close();
document.save(output);
document.close();
return output;
}
更新1:所以文件已经被创建,现在我只是在将它发送到网络时遇到麻烦,我正在使用ReactJS。我尝试调整我用来下载csv文件的结构,这里是代码:
const handleExportPDF = fileName => {
FileController.retrievePDF().then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
});
};
static retrievePDF() {
const { method, url } = endpoints.retrievePDF();
return api[method](url,{
responseType: "application/pdf"
});
}
export const fileEndpoints = {
retrievePDF: () => ({
method: "get",
url: `/export/dataPDF`
})
};
更新2:如果有人偶然来到这里,我已经能够通过这里的答案解决了这个问题:https://stackoverflow.com/questions/21729451/pdf-blob-pop-up-window-not-showing-content。关键是将
responseType: "application/pdf"
更改为responseType: 'arraybuffer'
虽然只是更改了这个,但我还将
window.URL.createObjectURL(new Blob([response.data]));
更改为window.URL.createObjectURL(new Blob([response.data]), {type: 'application/pdf'});
英文:
I've seen many answers here, I copied some examples and tried applying it, but I don't know how to make this work. I'm trying to create a file with PDFBox and sending it with a Response so the user can download it. So far, I'm able to download the file, but it is blank. I already tried just loading an example file from my computer with PDFBox and downloading it, but it comes the same way, blank. The code I am working with now is:
@GET
@Path("/dataPDF")
@Produces("application/pdf")
public Response retrievePDF(){
try {
ByteArrayOutputStream output = new ByteArrayOutputStream();
output = createPDF();
ResponseBuilder response = Response.ok(output.toByteArray(), "application/pdf");
response.header("Content-Disposition","attachment; filename=file.pdf");
return response.build();
}
catch (Exception ex) {
ex.printStackTrace();
return Response.status(Response.Status.NOT_FOUND).build();
}
public ByteArrayOutputStream createPDF() throws IOException {
PDFont font = PDType1Font.HELVETICA;
PDPageContentStream contentStream;
ByteArrayOutputStream output =new ByteArrayOutputStream();
PDDocument document =new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
contentStream = new PDPageContentStream(document, page);
contentStream.beginText();
contentStream.setFont(font, 20);
contentStream.newLineAtOffset(10, 770);
contentStream.showText("Amount: $1.00");
contentStream.endText();
contentStream.beginText();
contentStream.setFont(font, 20);
contentStream.newLineAtOffset(200, 880);
contentStream.showText("Sequence Number: 123456789");
contentStream.endText();
contentStream.close();
document.save(output);
document.close();
return output;
}
UPDATE 1: So the file is being created, now I'm justing having trouble sending it to the web, I'm using ReactJS. I tried adapting the structure I used to download a csv file, here it is:
const handleExportPDF= fileName => {
FileController.retrievePDF().then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
});
};
static retrievePDF() {
const { method, url } = endpoints.retrievePDF();
return api[method](url,{
responseType: "application/pdf"
});
}
export const fileEndpoints = {
retrievePDF: () => ({
method: "get",
url: `/export/dataPDF`
})
};
UPDATE 2: If someone ever stumbles here, I was able to solve the problem with this answers here: https://stackoverflow.com/questions/21729451/pdf-blob-pop-up-window-not-showing-content. The point was changing
responseType: "application/pdf"
to responseType: 'arraybuffer'
And even though it already works just changing this, I also changed
window.URL.createObjectURL(new Blob([response.data]));
to window.URL.createObjectURL(new Blob([response.data]), {type: 'application/pdf'});
答案1
得分: 1
使用以下测试代码,您可以验证您用于生成PDF的源代码是否基本正常工作。
但是,第二个文本元素的定位超出了视口范围。
看起来您的问题与Web框架有关。您可能需要提供更多关于此问题的详细信息以获取进一步的建议。
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.19</version>
</dependency>
</dependencies>
</project>
App.java
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import java.io.*;
public class App {
public static void main(String[] args) throws IOException {
File resultFile = File.createTempFile("Test",".pdf");
ByteArrayOutputStream byteArrayOutputStream = createPDF();
try(OutputStream outputStream = new FileOutputStream(resultFile)) {
byteArrayOutputStream.writeTo(outputStream);
}
System.out.println("Please find your PDF File here: " + resultFile.getAbsolutePath());
}
public static ByteArrayOutputStream createPDF() throws IOException {
PDFont font = PDType1Font.HELVETICA;
PDPageContentStream contentStream;
ByteArrayOutputStream output = new ByteArrayOutputStream();
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
contentStream = new PDPageContentStream(document, page);
contentStream.beginText();
contentStream.setFont(font, 20);
contentStream.newLineAtOffset(10, 770);
contentStream.showText("Amount: $1.00");
contentStream.endText();
contentStream.beginText();
contentStream.setFont(font, 20);
// 200 is way too much right and 800 too much on top... so this won't be visible on normal A4 Format
contentStream.newLineAtOffset(200, 880);
contentStream.showText("Sequence Number: 123456789");
contentStream.endText();
contentStream.close();
document.save(output);
document.close();
return output;
}
}
英文:
With the Testcode below you can verify that your Sourcecode for PDF generation works in general.
But the positioning of the second Textelement is out of the Viewport.
Looks like your problem is related to the Webframework. You might give more details about this for further advice.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.19</version>
</dependency>
</dependencies>
</project>
App.java
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import java.io.*;
public class App {
public static void main(String[] args) throws IOException {
File resultFile = File.createTempFile("Test",".pdf");
ByteArrayOutputStream byteArrayOutputStream = createPDF();
try(OutputStream outputStream = new FileOutputStream(resultFile)) {
byteArrayOutputStream.writeTo(outputStream);
}
System.out.println("Please find your PDF File here: " + resultFile.getAbsolutePath());
}
public static ByteArrayOutputStream createPDF() throws IOException {
PDFont font = PDType1Font.HELVETICA;
PDPageContentStream contentStream;
ByteArrayOutputStream output =new ByteArrayOutputStream();
PDDocument document =new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
contentStream = new PDPageContentStream(document, page);
contentStream.beginText();
contentStream.setFont(font, 20);
contentStream.newLineAtOffset(10, 770);
contentStream.showText("Amount: $1.00");
contentStream.endText();
contentStream.beginText();
contentStream.setFont(font, 20);
// 200 is way too much right and 800 too much on top... so this want be visible on normal A4 Format
contentStream.newLineAtOffset(200, 880);
contentStream.showText("Sequence Number: 123456789");
contentStream.endText();
contentStream.close();
document.save(output);
document.close();
return output;
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论