Чтение арабских вложений с использованием JavaMail - PullRequest
2 голосов
/ 16 октября 2011

У меня проблема с загрузкой файлов арабских вложений с использованием Java-почты.

Имя файла всегда неоднозначно.

Проблема в том, что Bodypart извлекает вложение как символы не-UTF-8.

private void getAttachments(Message temp) throws IOException, MessagingException {
    List<File> attachments = new ArrayList<File>();

    Multipart multipart = (Multipart) temp.getContent();

    System.out.println(multipart.getCount());

    for (int i = 0; i < multipart.getCount(); i++) {
        BodyPart bodyPart = multipart.getBodyPart(i);
        if (!Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {
            continue; // dealing with attachments only
        }
        InputStream is = bodyPart.getInputStream();

        // getFilename always have wrong characters set 
        byte [] fileBytes = bodyPart.getFileName().toString().getBytes();

        String filename = new String(fileBytes, "UTF-8");            

        File f = new File("C:\\Attachments\\" + filename);

         System.out.println(f .getName());

         try {
        if (f == null) {
            //filename = File.createTempFile("VSX", ".out").getName();
            return;
        }

        FileOutputStream fos = new FileOutputStream(f );
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        BufferedInputStream bis = new BufferedInputStream(is);

        int aByte;
        while ((aByte = bis.read()) >=0) {
            bos.write(aByte);
        }

        fos.flush();
        bos.flush();
        bos.close();
        bis.close();
        fos.close();
    } // end of try()
    catch (IOException exp) {
        System.out.println("IOException:" + exp);
    }        

        attachments.add(f);
    }
}

Ответы [ 3 ]

7 голосов
/ 16 октября 2011

Заголовок кодируется в соответствии с механизмом, описанным в RFC 2047 (это encoded-word), который говорит, что часть заголовка соответствует =??B??= - секция с байтовым кодированием. говорит о том, как интерпретировать байты, и (поскольку это стиль B, а не стиль Q) в кодировке Base-64.

Все это довольно сложно.К счастью, вы можете легко справиться с этим, используя статический метод javax.mail.internet.MimeUtility.decodeText().Это означает, что вы можете переключиться на это:

String filename = MimeUtility.decodeText(bodyPart.getFileName());

На самом деле, вам лучше сочетать это и со следующей строкой:

File f = new File("C:\\Attachments",
                  MimeUtility.decodeText(bodyPart.getFileName()));

Это лучше, потому что избегает больше проблемс созданием имен файлов, чем пытаясь сделать все это вручную.(Это также означает, что вы можете вывести это буквальное имя пути в какое-либо место конфигурации.)

3 голосов
/ 16 октября 2011

Эта часть мне кажется неработоспособной:

byte[] fileBytes = bodyPart.getFileName().toString().getBytes();
String filename = new String(fileBytes, "UTF-8");            

Вы используете кодировку платформы по умолчанию для кодирования имени файла (которое вы уже получили в виде строки) в байтахи затем декодирует их с использованием UTF-8.

Что не так с:

String filename = bodyPart.getFileName();

?Не делайте больше кодирования и декодирования, чем вам нужно.Конечно, может ли ваша файловая система обрабатывать такое имя файла, это другой вопрос, но, по крайней мере, вы больше не теряете данные на этом этапе ...

(Ваш метод копирования файла данные также неэффективны и оставят открытые потоки в случае исключений. Возможно, вы захотите взглянуть на Guava , чтобы написать простой код, который получает эту запись ...)

2 голосов
/ 16 октября 2011

попробовать:

String decoded = MimeUtility.decodeText(part.getFileName()); 
return Normalizer.normalize(decoded, Normalizer.Form.NFC); 
...