使用JavaMail阅读阿拉伯语附件

时间:2011-10-16 08:03:49

标签: java javamail

我遇到使用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 个答案:

答案 0 :(得分:7)

标头根据RFC 2047(encoded-word)中描述的机制进行编码,该机制表示标题的一部分与=? &lt; encoding&gt; {匹配{1}} &lt; encoded-bytes&gt; ?B?是字节编码的部分。 &lt; encoding&gt; 说明如何解释字节,并且(因为它是?=样式,而不是B样式)&lt; encoded-bytes&gt; 是base-64编码的。

这一切都相当复杂。幸运的是,您可以使用静态Q方法轻松处理此问题。这意味着您可以切换到:

javax.mail.internet.MimeUtility.decodeText()

实际上,你最好将它与下一行结合起来:

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

它更好,因为它避免了构建文件名的麻烦,而不是手动完成所有操作。 (这也意味着您可以将该文字路径名分解为某个配置位置。)

答案 1 :(得分:3)

这部分似乎对我不了解:

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

您使用默认平台编码将编码文件名(您已经将其作为字符串获取)作为字节,然后解码使用UTF- 8。

出了什么问题:

String filename = bodyPart.getFileName();

?不要再进行编码和解码了。当然,你的文件系统是否可以处理这样的文件名是另一回事,但至少你现在不会丢失数据......

(您复制文件数据的方法也非常低效,在异常情况下会留下开放流。您可能需要查看Guava来编写简单的代码这写......)

答案 2 :(得分:2)

尝试:

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