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

Telegram sendPhoto通过multipart/form-data传图报错400问题

问题背景

我正在实现Telegram Bot的图片发送功能,根据Telegram官方文档说明,sendPhoto接口支持使用multipart/form-data格式上传本地文件。

sendPhoto接口官方文档说明

现有实现代码

// 已确认目标文件真实存在
$file = File::get(Storage::disk('local')->path('test.jpeg')); // 等效于file_get_contents()读取文件内容

// 第一种实现:使用longman/telegram-bot库
$serverResponse = Request::sendPhoto([
    'chat_id' => $this->tg_user_chat_id,
    'photo' => $file
]);

// 第二种实现:直接用Guzzle发请求,排除库本身的问题
$client = new Client();
$response = $client->post("https://api.telegram.org/$telegram->botToken/sendPhoto", [
    'multipart' => [
        [
            'name'     => 'photo',
            'contents' => $file
        ],
        [
            'name'     => 'chat_id',
            'contents' => $this->tg_user_chat_id
        ]
    ]
]);

Log::info('_response', ['_' => $response->getBody()]);
Log::info(env('APP_URL') . "/storage/$url");
Log::info('response:', ['_' => $serverResponse->getResult()]);
Log::info('ok:', ['_' => $serverResponse->getOk()]);
Log::info('error_code:', ['_' => $serverResponse->getErrorCode()]);
Log::info('raw_data:', ['_' => $serverResponse->getRawData()]);

报错现象

两种实现方式返回完全一致的错误响应:

{"ok":false,"error_code":400,"description":"Bad Request: invalid file HTTP URL specified: Wrong URL host"}

目前通过文件ID、公网URL传图的方式均可正常运行,仅本地文件上传路径报错。

问题原因与修复方案

报错核心原因是两种写法都没有正确标识上传的内容为本地文件,Telegram服务端收到photo字段的内容后,默认将其识别为URL/文件ID字符串做解析,最终触发URL格式非法错误。

  • 针对Guzzle直接调用的写法:不要提前读取文件二进制内容传入,改为传入fopen打开的文件资源句柄,同时显式指定上传文件名,Guzzle会自动按文件附件格式组装multipart请求:
$client = new Client();
$response = $client->post("https://api.telegram.org/$telegram->botToken/sendPhoto", [
    'multipart' => [
        [
            'name'     => 'photo',
            'contents' => fopen(Storage::disk('local')->path('test.jpeg'), 'r'),
            'filename' => 'test.jpeg' // 必须显式指定文件名,否则不会识别为文件上传
        ],
        [
            'name'     => 'chat_id',
            'contents' => $this->tg_user_chat_id
        ]
    ]
]);
  • 针对longman/telegram-bot库的写法:不要传入读取后的文件二进制内容,使用库提供的encodeFile方法包装本地文件绝对路径,库内部会自动处理文件上传逻辑:
$serverResponse = Request::sendPhoto([
    'chat_id' => $this->tg_user_chat_id,
    'photo' => Request::encodeFile(Storage::disk('local')->path('test.jpeg'))
]);
  • 补充校验项:
    • 确认上传的图片大小不超过Telegram普通图片接口5MB的限制
    • 确认文件MIME类型为Telegram支持的jpg/png/gif等图片格式
    • 确认程序对目标文件有读取权限,fopen打开资源时不会返回false

内容的提问来源于stack exchange,提问作者pibocik125

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 00:57:22