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

如何使用WTelegramClient(C#)获取Telegram对话头像的远程URL

如何使用WTelegramClient(C#)获取Telegram对话头像的远程URL

我来帮你捋清楚这个问题:首先Telegram官方并没有提供可以直接调用的公开头像URL,那些你在网页端看到的https://t.me/i/userpic/...这类链接,其实是Telegram内部使用的非公开接口——不仅可能随时失效,而且在很多场景下需要验证才能访问,并不适合在自己的UI里直接依赖。

不过针对你的需求(不在本地存储头像,直接在Web UI展示),有两个可行的方案:

方案1:搭建自己的头像代理接口(推荐)

这个方案的思路是:后端用WTelegramClient直接下载头像的字节流,然后通过你自己的API接口把字节流返回给前端——既不用把头像存到本地磁盘,也能稳定地给前端提供可访问的头像地址。

步骤1:修改头像获取逻辑,返回字节流

先把你原来的GetAvatarUriAsync改成获取内存流的形式,不用存文件:

private async Task<byte[]?> GetAvatarBytesAsync(IPeerInfo peer)
{
    try
    {
        using var memoryStream = new MemoryStream();
        // 下载头像到内存流,true表示下载最大分辨率的头像
        await _client.DownloadProfilePhotoAsync(peer, memoryStream, true);
        return memoryStream.ToArray();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"获取头像失败: {ex.Message}");
        return null;
    }
}

步骤2:新增Web API接口返回头像

如果你的项目是ASP.NET Core,可以加一个专门的头像控制器,前端通过这个接口获取头像:

[ApiController]
[Route("api/avatars")]
public class AvatarController : ControllerBase
{
    private readonly YourTelegramBackgroundService _telegramService;
    private readonly IMessageStore _messageStore;

    public AvatarController(YourTelegramBackgroundService telegramService, IMessageStore messageStore)
    {
        _telegramService = telegramService;
        _messageStore = messageStore;
    }

    [HttpGet("{peerId}")]
    public async Task<IActionResult> GetAvatar(long peerId)
    {
        // 从你的存储里找到对应的User或Chat
        var chat = await _messageStore.GetChatByIdAsync(peerId);
        IPeerInfo? peer = chat;
        if (chat == null)
        {
            var user = await _messageStore.GetUserByIdAsync(peerId);
            peer = user;
        }

        if (peer == null)
            return NotFound("找不到对应的对话对象");

        var avatarBytes = await _telegramService.GetAvatarBytesAsync(peer);
        if (avatarBytes == null)
            return NotFound("该对象没有设置头像");

        // 把字节流作为图片返回给前端
        return File(avatarBytes, "image/jpeg");
    }
}

步骤3:在原代码里关联ID

在你原代码的AddOrUpdateChatAsync和AddOrUpdateUserAsync之后,每个Chat/User都会存在你的存储里,带有对应的ID。前端只需要请求/api/avatars/{peerId}就能拿到头像,完全不需要本地存储。

方案2:构造Telegram内部头像链接(不推荐)

如果你一定要类似t.me的远程URL,可以逆向构造出格式,但要注意这个方法没有官方保障,随时可能失效:

  • 用户头像格式:https://t.me/i/userpic/320/{userId}_{accessHash}.jpg
  • 群聊头像格式:https://t.me/i/grouppic/{chatId}_{accessHash}.jpg

你可以在原代码里添加构造链接的方法:

private string? ConstructAvatarUrl(IPeerInfo peer)
{
    return peer switch
    {
        User u => $"https://t.me/i/userpic/320/{u.id}_{u.access_hash}.jpg",
        Chat c => $"https://t.me/i/grouppic/{c.ID}_{c.access_hash}.jpg",
        _ => null
    };
}

然后在原代码的头像位置调用:

// 假设你在存储Chat/User的时候把这个URL也存起来
if (peer is User user)
{
    var avatarUrl = ConstructAvatarUrl(user);
    await store.UpdateUserAvatarUrlAsync(user.id, avatarUrl);
}
else if (peer is Chat chat)
{
    var avatarUrl = ConstructAvatarUrl(chat);
    await store.UpdateChatAvatarUrlAsync(chat.ID, avatarUrl);
}

注意事项

  • 这类链接可能需要Telegram的验证信息,在一些浏览器或环境下可能无法直接访问
  • Telegram随时可能修改这个链接格式,导致你的UI突然丢失头像
  • 部分隐私设置高的用户/群聊,这类链接可能直接返回403或404

总结

最稳定可靠的方案是自己搭建代理接口,既满足你“不本地存储”的需求,也能保证头像的长期可访问性。构造内部链接的方式只适合临时测试,不适合生产环境使用。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 08:58:01