使用kotlogram获取Telegram消息媒体异常:仅能获取最后一个媒体文件
解决Telegram多媒体消息仅获取最后一个媒体文件的问题
你的代码当前只能获取单媒体消息的内容,遇到多媒体消息时仅能拿到最后一个媒体文件,核心问题是未处理Telegram的多媒体消息容器TLMessageMediaAlbum,同时下载逻辑的位置错误导致覆盖了之前的媒体数据。
问题分析
- Telegram的多媒体消息(如一组图片/文件)是通过
TLMessageMediaAlbum类型封装的,原代码只处理了单个的TLMessageMediaPhoto和TLMessageMediaDocument,完全忽略了相册类型 - 下载操作
client.downloadSync()放在外层循环中,每次循环都会覆盖fos、Input和size的内容,最终只下载了最后一个媒体 messageText的赋值逻辑有误,多媒体消息的文本通常在TLMessage的message字段,而非单个媒体的caption(媒体的caption是该媒体的附加说明)
修复后的代码
try { val ROOT_DIR = "C:\\fopii" // 获取最新的1条消息 val tl = client.messagesGetHistory(inputPeer, 0, 0, 0, 1, 0, 0) val messages = tl.messages var mediaIndex = 0 for (msg in messages) { if (msg is TLMessage) { // 优先取消息本身的文本,而非媒体的caption val messageText = msg.message.takeIf { it.isNotEmpty() } ?: "" println("消息文本: $messageText") val media = msg.media when (media) { // 单张图片 is TLMessageMediaPhoto -> { mediaIndex++ val filename = "photo$mediaIndex.jpg" val fileLocation = media.getMediaInput()!!.inputFileLocation val fileSize = media.getMediaInput()!!.size // 直接在媒体处理逻辑内下载,避免覆盖 withContext(Dispatchers.IO) { FileOutputStream(File(ROOT_DIR, filename)).use { fos -> client.downloadSync(fileLocation, fileSize, fos) } } println("已下载图片: $filename") } // 单个文档/文件 is TLMessageMediaDocument -> { val tlDocument = media.document.asDocument val filename = tlDocument.attributes.stream() .filter { it is TLDocumentAttributeFilename } .findFirst() .map { (it as TLDocumentAttributeFilename).fileName } .orElse("file${mediaIndex++}.bin") val fileLocation = media.getMediaInput()!!.inputFileLocation val fileSize = media.getMediaInput()!!.size withContext(Dispatchers.IO) { FileOutputStream(File(ROOT_DIR, filename)).use { fos -> client.downloadSync(fileLocation, fileSize, fos) } } println("已下载文件: $filename") } // 多媒体相册(一组图片/文件) is TLMessageMediaAlbum -> { // 遍历相册内的所有媒体项 for (albumMedia in media.media) { mediaIndex++ when (albumMedia) { is TLMessageMediaPhoto -> { val filename = "photo$mediaIndex.jpg" val fileLocation = albumMedia.getMediaInput()!!.inputFileLocation val fileSize = albumMedia.getMediaInput()!!.size withContext(Dispatchers.IO) { FileOutputStream(File(ROOT_DIR, filename)).use { fos -> client.downloadSync(fileLocation, fileSize, fos) } } println("已下载相册图片: $filename") } is TLMessageMediaDocument -> { val tlDocument = albumMedia.document.asDocument val filename = tlDocument.attributes.stream() .filter { it is TLDocumentAttributeFilename } .findFirst() .map { (it as TLDocumentAttributeFilename).fileName } .orElse("album_file${mediaIndex}.bin") val fileLocation = albumMedia.getMediaInput()!!.inputFileLocation val fileSize = albumMedia.getMediaInput()!!.size withContext(Dispatchers.IO) { FileOutputStream(File(ROOT_DIR, filename)).use { fos -> client.downloadSync(fileLocation, fileSize, fos) } } println("已下载相册文件: $filename") } } } } else -> { println("不支持的媒体类型: ${media.javaClass.simpleName}") } } } } } catch (e: Exception) { e.printStackTrace() } finally { client.close() }
关键修改点
- 新增
TLMessageMediaAlbum的处理逻辑,遍历相册内的所有媒体项 - 将下载操作移至每个媒体项的处理逻辑内部,使用
use自动管理文件流,避免资源泄漏 - 修正消息文本的获取逻辑,优先取
TLMessage本身的message字段 - 优化文件名生成逻辑,避免覆盖,同时处理无文件名的文档情况
- 提取
ROOT_DIR为常量,避免重复定义
内容的提问来源于stack exchange,提问作者Loppllo Fg
相关产品推荐
相关产品推荐

