java 如何在不将文件存储在服务器端的情况下将 PDF 提供给浏览器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30456901/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 17:08:54  来源:igfitidea点击:

How can I serve a PDF to a browser without storing a file on the server side?

javapdfmodel-view-controllerpdf-generationitext

提问by Mishal Harish

I have two methods. One that generates a PDF at the server side and another that downloads the PDF at the client side.

我有两种方法。一个在服务器端生成 PDF,另一个在客户端下载 PDF。

How can i do this without storing it in the Server side and allow the client side to directly download this.

如何在不将其存储在服务器端并允许客户端直接下载它的情况下执行此操作。

The Following are the two methods:

以下是两种方法:

public void downloadPDF(HttpServletRequest request, HttpServletResponse response) throws IOException{

    response.setContentType("application/pdf");
    response.setHeader("Content-disposition","attachment;filename="+ "testPDF.pdf");
    FileInputStream fis = null;
    DataOutputStream os = null;

    try {
        File f = new File("C://New folder//itext3.pdf");
        response.setHeader("Content-Length",String.valueOf(f.length()));

        fis = new FileInputStream(f);
        os = new DataOutputStream(response.getOutputStream());
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = fis.read(buffer)) >= 0) {
            os.write(buffer, 0, len);
        }

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        fis.close();
        os.flush();
        os.close();
    }
    response.setHeader("X-Frame-Options", "SAMEORIGIN");
}

And:

和:

public Document generatePDF() {

    Document doc = new Document();
     try {
            File file = new File("C://New folder//itext_Test2.pdf");
            FileOutputStream pdfFileout = new FileOutputStream(file);
            PdfWriter.getInstance(doc, pdfFileout);

            doc.addAuthor("TestABC");
            doc.addTitle("Aircraft Details");
            doc.open();


            Anchor anchor = new Anchor("Aircraft Report");
            anchor.setName("Aircraft Report");

            Chapter catPart = new Chapter(new Paragraph(anchor), 1);

            Paragraph para1 = new Paragraph();
            Section subCatPart = catPart.addSection(para1);
            para1.add("This is paragraph 1");

            Paragraph para2 = new Paragraph();
            para2.add("This is paragraph 2");


            doc.add(catPart);

            doc.close();


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

回答by Bruno Lowagie

The people who advise you to use response.getOutputStream()instead of creating a FileOutputStreamare right. See for instance the HelloServlet from Chapter 9 of my book:

建议您使用response.getOutputStream()而不是创建 a 的人FileOutputStream是对的。例如,参见我的书第 9 章中的HelloServlet:

public class Hello extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        response.setContentType("application/pdf");
        try {
            // step 1
            Document document = new Document();
            // step 2
            PdfWriter.getInstance(document, response.getOutputStream());
            // step 3
            document.open();
            // step 4
            document.add(new Paragraph("Hello World"));
            document.add(new Paragraph(new Date().toString()));
            // step 5
            document.close();
        } catch (DocumentException de) {
            throw new IOException(de.getMessage());
        }
    }
}

However, some browsers experience problems when you send bytes directly like this. It's safer to create the file in memory using a ByteArrayOutputStreamand to tell the browser how many bytes it can expect in the content header:

但是,当您像这样直接发送字节时,某些浏览器会遇到问题。使用 a 在内存中创建文件ByteArrayOutputStream并告诉浏览器它可以在内容标题中期望多少字节更安全:

public class PdfServlet extends HttpServlet {

    protected void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        try {
            // Get the text that will be added to the PDF
            String text = request.getParameter("text");
            if (text == null || text.trim().length() == 0) {
                 text = "You didn't enter any text.";
            }
            // step 1
            Document document = new Document();
            // step 2
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PdfWriter.getInstance(document, baos);
            // step 3
            document.open();
            // step 4
            document.add(new Paragraph(String.format(
                "You have submitted the following text using the %s method:",
                request.getMethod())));
            document.add(new Paragraph(text));
            // step 5
            document.close();

            // setting some response headers
            response.setHeader("Expires", "0");
            response.setHeader("Cache-Control",
                "must-revalidate, post-check=0, pre-check=0");
            response.setHeader("Pragma", "public");
            // setting the content type
            response.setContentType("application/pdf");
            // the contentlength
            response.setContentLength(baos.size());
            // write ByteArrayOutputStream to the ServletOutputStream
            OutputStream os = response.getOutputStream();
            baos.writeTo(os);
            os.flush();
            os.close();
        }
        catch(DocumentException e) {
            throw new IOException(e.getMessage());
        }
    }
}

For the full source code, see PdfServlet. You can try the code here: http://demo.itextsupport.com/book/

有关完整的源代码,请参阅PdfServlet。您可以在此处尝试代码:http: //demo.itextsupport.com/book/

回答by mark_o

You are creating a FileOutputStream to generate pdf. But what you can do is to use the stream that is present in HttpServletResponse on server side method and write the file directly to it.

您正在创建一个 FileOutputStream 来生成 pdf。但是您可以做的是在服务器端方法上使用 HttpServletResponse 中存在的流并将文件直接写入其中。

回答by m4ktub

You can receive an OutputStreamin your generatePDFmethod. If you pass the response.getOutputStream()to the generate method then the PDF will be written to the response directly.

您可以OutputStream在您的generatePDF方法中收到一个。如果您将 传递response.getOutputStream()给 generate 方法,那么 PDF 将直接写入响应。

回答by Brett Walker

Just call this method appropriately from downloadPDF(); e.g.:

只需从downloadPDF(); 例如:

generatePDF(response.getOutputStream());

that calls this method:

调用这个方法:

public void generatePDF(OutputStream pdfOutputStream) {

    Document doc = new Document();
     try {
            PdfWriter.getInstance(doc, pdfOutputStream);

            doc.addAuthor("TestABC");
            doc.addTitle("Aircraft Details");
            doc.open();


            Anchor anchor = new Anchor("Aircraft Report");
            anchor.setName("Aircraft Report");

            Chapter catPart = new Chapter(new Paragraph(anchor), 1);

            Paragraph para1 = new Paragraph();
            Section subCatPart = catPart.addSection(para1);
            para1.add("This is paragraph 1");

            Paragraph para2 = new Paragraph();
            para2.add("This is paragraph 2");


            doc.add(catPart);

            doc.close();


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