JavaMail: получить размер MimeMessage

#java #jakarta-mail

#java #джакарта-почта

Вопрос:

Я пытаюсь получить размер MimeMessage. Метод getSize() просто всегда возвращает значение -1.

Это мой код:

 MimeMessage m = new MimeMessage(session);
m.setFrom(new InternetAddress(fromAddress, true));
m.setRecipient(RecipientType.TO, new InternetAddress(toAddress, true));
m.setSubject(subject);

MimeBodyPart bodyPart = new MimeBodyPart();
bodyPart.setContent(body, "text/html");
Multipart mp = new MimeMultipart();
mp.addBodyPart(bodyPart);
m.setContent(mp);

m.getSize(); // -1 is returned
  

ЭТО ОТВЕТ НА МОЙ ВОПРОС:

 ByteArrayOutputStream os = new ByteArrayOutputStream();
m.writeTo(os);
int bytes = os.size();
  

Ответ №1:

Более эффективным решением, но требующим внешней библиотеки, является следующее:

 public static long getReliableSize(MimeMessage m) throws IOException, MessagingException {
    try (CountingOutputStream out = new CountingOutputStream(new NullOutputStream())) {
        m.writeTo(out);
        return out.getByteCount();
    }
}
  

Как CountingOutputStream, так и NullOutputStream доступны в Apache Common IO. Это решение не требует работы с временным байтовым буфером (запись, выделение, перераспределение и т.д.)

Комментарии:

1. Я вижу огромную разницу в количестве байтов, возвращаемых из библиотеки apache, когда сравниваю его с выводом Java mime message.getSize(). есть идеи по этому поводу?

Ответ №2:

Решение, предоставляемое Apache Commons, хорошее, но конструктор NullOutputStream() теперь устарел. Вместо этого используйте синглтон:

 CountingOutputStream out = new CountingOutputStream(NullOutputStream.NULL_OUTPUT_STREAM);
  

Ответ №3:

попробуйте вызвать mp.getSize(), чтобы посмотреть, что он возвращает, MimeMessage вызывает его только для mp. Также из MIME message API

Возвращает размер содержимого этой части в байтах. Возвращает -1, если размер не может быть определен.

На данный момент вы не передали никакого содержимого в сообщение, что может быть причиной возвращаемого значения -1.

Комментарии:

1. Что вы имеете в виду, что я не передал никакого содержимого? Я выполнил m.setContent (mp)

2. BodyPart.getSize() возвращает -1

3. добавьте некоторое содержимое в тело .. после этого должен получиться приблизительный размер.

4. Если кто-то все еще смотрит на это, MimeMessage и MimeBodyPart запускают getSize() для объекта содержимого или потока содержимого. Они задаются конструкторами, но не setContent(), поэтому, даже если getContent() возвращает данные, getSize() ошибочно вернет значение -1. Используйте отладчик для отслеживания внутренних данных, поскольку они могут храниться в нескольких местах в datahandler. Например, вложения могут быть измерены путем вызова available() во входном потоке источника данных datahandler.