2011-05-04 50 views
3

我需要创建一个电子邮件,其中包含一个动态组成的附件。在我的初稿中,我将附件构建为一个String。但是在代码中,其他人指出,字符串可能非常大。它通常是几千字节,但偶尔它可能是兆字节。所以他们说我应该将它逐行写入临时文件,然后将文件附加到电子邮件中。否则,我可能会用完堆空间。在发送前javamail是否将附件加载到内存中?

我想知道这是否有帮助。如果JavaMail在发送之前将整个文件读入内存,则不会有任何区别。当然,创建一个临时文件引入了其他的烦恼,比如找到一个合适的目录来放置它,确保我拥有权限等等。但是,如果Javamail以一些适度大小的块读取文件,那么它会避免无用的,内存问题。

一个问题是:据我了解,Javamail同步发送。所以,如果我创建文件,发送它,然后删除文件,那么在文件实际发送之前不应该有删除文件的问题,对吧?

+1

JavaMail内部似乎是相当不错的流数据,而不是缓冲它。有几种情况可以缓冲,但这些都是例外而非规则。如果您不想单步执行源代码,那么一个简单的实验就是将8 MB的堆分配给您的java进程并尝试发送一个10 MB的文件。 – dnault 2011-05-04 20:44:20

+1

哦,是的,在调用send方法之后立即删除文件是安全的。 – dnault 2011-05-04 20:46:56

+0

@dnault:简单测试的好处。我通常很快进行实证测试,而不是从哲学角度进行思考,但出于某种原因,我的大脑冻结了,并没有想到这个简单的实验。 – Jay 2011-05-09 13:48:43

回答

3

如果您使用DataHandler实现,那么您可以对其进行流式处理。我们做这一切的时候

  MimeBodyPart mbp2 = new MimeBodyPart(); 
      // attach the file to the message 
      mbp2.setDataHandler(new DataHandler(fids[i])); 
      mbp2.setFileName(fids[i].getName()); 

哪里FIDS [I]在这个例子是我们自己实现的DataSource接口由MJB描述将被作为一个附件创建

public abstract interface javax.activation.DataSource { 

    // Method descriptor #4()Ljava/io/InputStream; 
    public abstract java.io.InputStream getInputStream() throws java.io.IOException; 

    // Method descriptor #8()Ljava/io/OutputStream; 
    public abstract java.io.OutputStream getOutputStream() throws java.io.IOException; 

    // Method descriptor #10()Ljava/lang/String; 
    public abstract java.lang.String getContentType(); 

    // Method descriptor #10()Ljava/lang/String; 
    public abstract java.lang.String getName(); 
} 
+0

谢谢。但我的问题的目的不是,“我可以使用文件作为附件吗?”,但是,“当我做什么时,内存中会发生什么?”即JavaMail是否将整个内容加载到内存中然后发送它,还是以小块的形式读取文件以发送? – Jay 2011-05-09 13:46:36

+0

它将其作为流读取。它不会将其缓冲在内存中。为了证明这一点,请在64 MB JVM中附加100 MB附件.... no OOM。 (我可以告诉你,我已经用JavaMail 1.4进行了这个测试,但是如果你想证明它(一个好的和有价值的目标),很容易这样做 - 你拥有了你需要的所有东西。 – MJB 2011-05-09 15:16:58

2

消息,我怀疑你是这么想的。这一个更简单,并从文件发送消息作为正文:

File file = new File("huge-message.txt"); 
MimeMessage msg = new MimeMessage(mailSession); 
msg.setFrom(...); 
msg.setRecipient(...); 
msg.setSubject(...); 
msg.setDataHandler(new DataHandler(new FileDataSource(file))); 
+0

其实在我现在的情况是我希望它成为一个附件:我们将一个报告附加到一封电子邮件中,我们希望电子邮件简单地说出“附加报告XXX”,然后用户可以选择保存报告文件。 – Jay 2011-07-20 13:38:21

+0

您的观点是有效的(事实上​​,我们的代码也支持大文本体) - 我只是保持问题的空间问题,因为它是一个很好的添加 – MJB 2011-07-20 17:08:51