使用JakartaMail实现邮件附件保存与展示的最佳方案咨询
实现方案
存储逻辑说明
- 不需要统一转换为Bitmap格式存储:Bitmap仅适用于图片类型附件,PDF、文档、压缩包等其他格式附件无法通过Bitmap存储,最优方案是直接读取附件的原始二进制流写入内部存储,完全保留文件原始格式,避免转换产生的性能损耗和信息丢失。
- 存储路径选择应用专属内部存储目录,不需要申请额外读写权限,数据仅当前应用可访问,安全性更高,写入完成后将完整文件路径存入本地数据库即可后续调用。
具体代码实现
首先实现附件写入内部存储的工具方法:
// 传入Context和邮件BodyPart,返回保存后的绝对路径,保存失败返回null private fun saveAttachmentToInternalStorage(context: Context, bodyPart: BodyPart): String? { // 处理附件文件名,替换非法字符避免写入失败 val originalFileName = bodyPart.fileName?.replace(Regex("[\\\\/:*?\"<>|]"), "_") ?: return null // 创建专属附件存储目录 val attachmentDir = File(context.filesDir, "mail_attachments") if (!attachmentDir.exists()) { attachmentDir.mkdirs() } val targetFile = File(attachmentDir, originalFileName) return runCatching { // 直接读输入流写入文件,不需要格式转换 bodyPart.inputStream.use { input -> targetFile.outputStream().use { output -> input.copyTo(output) } } targetFile.absolutePath }.getOrNull() }
修改原有的邮件解析方法,补充附件处理逻辑:
// 此处将返回值第一个参数调整为附件路径列表,适配多附件场景;如果需要返回字符串可自行用分隔符拼接列表 private fun parseMailContent(context: Context, multipart: Multipart): Pair<List<String>, MessageContent> { val messageContent = MessageContent() val attachmentPaths = mutableListOf<String>() for (i in 0 until multipart.count) { val bodyPart: BodyPart = multipart.getBodyPart(i) val disposition: String? = bodyPart.disposition // 处理附件逻辑 if (disposition != null && disposition.equals("ATTACHMENT", ignoreCase = true)) { saveAttachmentToInternalStorage(context, bodyPart)?.let { path -> attachmentPaths.add(path) } // 附件不需要解析文本,直接跳过后续逻辑 continue } // 处理文本内容 val contentType = bodyPart.contentType when { contentType.contains("TEXT/PLAIN", ignoreCase = true) -> { messageContent.text += bodyPart.content.toString() } contentType.contains("TEXT/HTML", ignoreCase = true) -> { messageContent.html += bodyPart.content.toString() } // 原逻辑中的else分支会清空已解析的正文,建议删除,避免内嵌资源等非文本非附件内容误清空正文 } } return Pair(attachmentPaths, messageContent) }
附件展示逻辑
后续读取数据库中存储的文件路径生成File对象后,按文件后缀/MIME类型匹配对应展示方式即可:
- 图片类附件:直接用Coil、Glide等图片加载框架加载File对象
- PDF类附件:调用系统PDF阅读器或第三方PDF加载库加载File对象
- 其他格式附件同理,按MIME类型匹配对应打开工具即可
内容的提问来源于stack exchange,提问作者Antonio
相关产品推荐
相关产品推荐

