将电子邮件作为流发送PDF附件

11

我想将Pdf作为电子邮件附件发送(使用JavaMail API)。我已经有了Pdf文件(由jasper生成),存储在byte[]中。

public InputStream exportPdfToInputStream(User user) throws ParseErrorException, MethodInvocationException, ResourceNotFoundException, JRException, IOException{
        JasperPrint jasperPrint = createJasperPrintObject(user);
        byte[] pdfByteArray = JasperExportManager.exportReportToPdf(jasperPrint);
        return new ByteArrayInputStream(pdfByteArray);
    }

以下是我用来构造作为附件的MimeBodyPart的代码:

    if (arrayInputStream != null && arrayInputStream instanceof ByteArrayInputStream) {
        MimeBodyPart attachment = new MimeBodyPart(arrayInputStream);
        attachment.setHeader("Content-Type", "application/pdf");
        mimeMultipart.addBodyPart(attachment);
    }

这段代码给我返回了这个错误:

javax.mail.MessagingException: IOException while sending message;
  nested exception is:
    java.io.IOException: Error in encoded stream: needed at least 2 valid base64 characters, but only got 1 before padding character (=), the 10 most recent characters were: "\24\163\193\n\185\194\216#\208="
2个回答

23

我在这个帖子中找到了一个解决方案。似乎有一个专门为此目的创建的DataSource类。希望这个例子也能帮助其他人。

    if (arrayInputStream != null && arrayInputStream instanceof ByteArrayInputStream) {
        // create the second message part with the attachment from a OutputStrean
        MimeBodyPart attachment= new MimeBodyPart();
        ByteArrayDataSource ds = new ByteArrayDataSource(arrayInputStream, "application/pdf"); 
        attachment.setDataHandler(new DataHandler(ds));
        attachment.setFileName("Report.pdf");
        mimeMultipart.addBodyPart(attachment);
    }

2
这将完全读取InputStream并且字节数组完全存储在ByteArrayDataSource中。因此,对于大附件,您将具有高内存使用率。对吧? - Tama

6

您所使用的构造函数是用于从传输中解析 mime 部分的。

您的第二个示例应该可以正常工作。您可以考虑:

  • 不要将其转换为 InputStream 并返回,这样会造成不必要的副本。
  • 添加一个附件(例如,bp.setDisposition(Part.ATTACHMENT);

@mtraut:你说不要将它转换为InputStream再转回来,但是如果没有InputStream我该怎么办呢? - Atticus
1
使用**ByteArrayDataSource(byte[] data, String type)**构造函数和"pdfByteArray"。 - mtraut
@mtraut:谢谢,这正是我在答案中提交的内容。但还是谢谢你。我认为还有一种更简单的方法来完成它! - Atticus
@Atticus - 不完全正确。在你的回答中,你使用了INputStream构造函数,这会导致另一个拷贝... - mtraut
@mtraut:好的,现在我明白了。还有一个问题……为什么需要setDisposition方法?不设置它也可以正常工作。 - Atticus
1
使用“disposition”,您可以尝试控制客户端处理该部分的方式。虽然并非所有类型的实现都正确地对此进行验证,但“attachment”肯定会产生预期的行为。虽然在使用PDF附件时几乎没有风险,但是如果未正确声明,“text / html”或“text / plain”附件可能会在电子邮件中内联呈现。请考虑这样做是良好的风格... - mtraut

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接