You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用kotlogram获取Telegram消息媒体异常:仅能获取最后一个媒体文件

解决Telegram多媒体消息仅获取最后一个媒体文件的问题

你的代码当前只能获取单媒体消息的内容,遇到多媒体消息时仅能拿到最后一个媒体文件,核心问题是未处理Telegram的多媒体消息容器TLMessageMediaAlbum,同时下载逻辑的位置错误导致覆盖了之前的媒体数据。

问题分析

  1. Telegram的多媒体消息(如一组图片/文件)是通过TLMessageMediaAlbum类型封装的,原代码只处理了单个的TLMessageMediaPhoto和TLMessageMediaDocument,完全忽略了相册类型
  2. 下载操作client.downloadSync()放在外层循环中,每次循环都会覆盖fos、Input和size的内容,最终只下载了最后一个媒体
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 08:55:01