【问题标题】:java How to combine itextpdf and java mail?java如何结合itextpdf和java邮件?
【发布时间】:2017-11-29 14:28:00
【问题描述】:

嘿,我正在开发一个 Web 应用程序,但我在组合 2 个功能时遇到了问题(构建一个 pdf 并将其作为附件与电子邮件一起发送)。两个部分分别工作,但我不知道如何获取创建的 PDF 的文件路径以将其添加到邮件附件中。

以下是重要的coden-ps:

  1. 我使用 java servlet CreatePDF 创建了一个新的 PDF 文件(使用 itext 5)并在新选项卡中显示它:

创建PDF Servlet:

    //initial new ByteArrayOutputStream
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    //get absolute path of the logo
    String relativeLogoWebPath = "/logo.jpg";
    String absoluteLogoDiskPath = getServletContext().getRealPath(relativeLogoWebPath);

    //build PDF with itextpdf
    new BuildPDF(baos, acc, absoluteLogoDiskPath, header, body, footer, vat);

    // setting the content type
    response.setHeader("Expires", "0");
    response.setHeader("Cache-Control","must-revalidate, post-check=0,precheck=0");
    response.setHeader("Pragma", "public");
    response.setContentType("application/pdf");
    response.setContentLength(baos.size());

    // write ByteArrayOutputStream to the ServletOutputStream
    OutputStream os = response.getOutputStream();
    baos.writeTo(os);
    os.flush();
    os.close();

BuildPDF 类:

public BuildPDF(ByteArrayOutputStream baos, Accounting acc, String absolutLogoPath, 
  Collection<String> header, Collection<String> body, Collection<String> footer, Double vat){
    //init document
    Document document = new Document(PageSize.A4, 60, 30, 140, 90);
    document.setMarginMirroring(false);

    //init pdf writer
    PdfWriter writer = PdfWriter.getInstance(document, baos);
    writer.setBoxSize("art", new com.itextpdf.text.Rectangle(36, 54, 559, 788));

    //add header and footer
    HeaderFooter event = new HeaderFooter(header, footer, absolutLogoPath);
    writer.setPageEvent(event);

    //open the document
    document.open();

    //add title and body
    addTitle(document, acc)
    addBody(document, acc, body, vat, writer);

    //close document and pdf writer
    document.close();
    writer.close();
}
  1. 在另一个选项卡中,我转到下一个 jsp 页面,单击按钮后(打开 servlet SendAccouningPage)应该可以通过电子邮件(使用 java 邮件)发送这个创建的 pdf:

SendAccountingPage Servlet:

//TODO: get path of created PDF
String[] attachFiles = new String[1]; 
//attachFiles[0] = (String) request.getSession().getAttribute("pdfPath");
//request.getSession().removeAttribute("pdfPath");

EmailUtility.sendEmailWithAttachments(host, port, fromMail, passwort,
     mail, subject, message, attachFiles);

EmailUtility 类:

 public static void sendEmailWithAttachments(String host, String port,
        final String userName, final String password, String toAddress,
        String subject, String message, String[] attachFiles)
        throws AddressException, MessagingException {

    // sets SMTP server properties
    Properties properties = new Properties();
    properties.put("mail.smtp.host", host);
    properties.put("mail.smtp.port", port);
    properties.put("mail.smtp.auth", "true");
    properties.put("mail.smtp.starttls.enable", "true");
    properties.put("mail.user", userName);
    properties.put("mail.password", password);

    // creates a new session with an authenticator
    Authenticator auth = new Authenticator() {
        public PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(userName, password);
        }
    };
    Session session = Session.getInstance(properties, auth);

    // creates a new e-mail message
    Message msg = new MimeMessage(session);

    msg.setFrom(new InternetAddress(userName));
    InternetAddress[] toAddresses = { new InternetAddress(toAddress) };
    msg.setRecipients(Message.RecipientType.TO, toAddresses);
    msg.setSubject(subject);
    msg.setSentDate(new Date());

    // creates message part
    MimeBodyPart messageBodyPart = new MimeBodyPart();
    messageBodyPart.setContent(message, "text/html");

    // creates multi-part
    Multipart multipart = new MimeMultipart();
    multipart.addBodyPart(messageBodyPart);

    // adds attachments
    if (attachFiles != null && attachFiles.length > 0) {
        for (String filePath : attachFiles) {
            MimeBodyPart attachPart = new MimeBodyPart();

            try {
                attachPart.attachFile(filePath);
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            multipart.addBodyPart(attachPart);
        }
    }

    // sets the multi-part as e-mail's content
    msg.setContent(multipart);

    // sends the e-mail
    Transport.send(msg);

}

那么有没有办法获取创建的 pdf 的文件路径并存储它,例如进入会议? (如果是:这条路径的阻力如何?如果我关闭带有创建的 pdf 的选项卡,它会丢失吗?)

如果没有:

否则我该如何组合它?

我是否必须保存 pdf(如果是:我必须做哪些机会,是否可以暂时保存它?)

【问题讨论】:

  • 我已经回答了您的问题,但我想知道您为什么选择使用 iText 5 而不是 iText 7。原因可能不止一个。例如:它是一个遗留项目,并且 iText 5 已经在代码库中。然而,我真正想要的答案是:我们如何推广 iText 7?我们如何提高 iText 7 的采用率?我的印象是开发人员不知道他们可以通过在iText 7 platform 之上开发附加组件来赚钱。
  • 嘿,原因很简单:这是我的第一个网络项目,所以在开发之前我必须学习很多新东西。我早些时候使用 iText 5,所以我知道这会像我想要的那样工作。所以我节省了一点时间来使用已知的旧版本 =) 但我喜欢 iText,而且我确信当我完成这个项目时我会使用 iText 7。 (如果我在完成这个项目后还有时间的话,也许我也会改变这个项目中的版本)

标签: java jsp servlets itext jakarta-mail


【解决方案1】:

您正在使用 ByteArrayOutputStream(命名为 baos)在内存中创建 PDF,然后将此文件写入 servlet 的输出流:

OutputStream os = response.getOutputStream();
baos.writeTo(os);

这是一种很好的做法,但也有另一种方法。 ByteArrayOutputStream 有一个名为 toByteArray() 的方法,所以你也可以这样做:

OutputStream os = response.getOutputStream();
byte[] bytes = baos.toByteArray();
os.write(bytes, 0, bytes.length);
os.flush();
os.close();

现在您在名为bytesbyte[] 中有完整的文件,您需要调整您的EmailUtility 类,以便它接受字节数组而不是文件路径。这在以下问题的答案中得到了解释:Mail Attachments with byte array:

MimeBodyPart att = new MimeBodyPart(); 
ByteArrayDataSource bds = new ByteArrayDataSource(byte, "application/pdf"); 
att.setDataHandler(new DataHandler(bds));
att.setFileName(bds.getName());

这就是您发送带有文件附件的邮件的方式,该文件是在内存中创建的,从不作为文件存储在服务器上的磁盘上。

【讨论】:

  • 嘿谢谢你的回答。我以这种方式更改它,但现在我得到一个 javax.mail ParseException: In Conten-Type string expected '/', got null
  • (更改更具体:)我将 byte[] 文件保存在会话中并在 SendAccountingPage 中获取它。我还将 EmailUtility 中的参数从 String[] attachFile 更改为 byte[] 并在 1. 参数处调用它 new ByteArrayDataSource(attachFile, "result.pdf");
  • 你的 cmets 看起来像英语,但这是我不懂的英语。
  • 哈哈好吧对不起。我不是一个出色的口语人才,也不是在实践中。我再试一次:
  • 我如上所述更改了我的代码,但现在我每次都得到这个 Exeption:“javax.mail.internet.ParseExeption: In Content-Type string , expected '/',为空”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-26
相关资源
最近更新 更多