2011-05-04 52 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