如何使用Node.js的Telegraf模块下载Telegram机器人收到的文件或图片
如何用Telegraf下载Telegram机器人收到的图片/文件
嘿,我来帮你搞定这个问题~你之前的代码误区在于,https://api.telegram.org/bot1234-ABCD/getFile?file_id=${picture} 只是一个API请求地址,直接把它赋值给photo变量后,它只是个普通字符串,根本没有file_path属性。你得先发送HTTP请求调用这个API,拿到返回的文件路径,才能拼接出真正的下载链接。
下面给你两种靠谱的实现方式,都是基于Node.js的Telegraf框架:
方法一:用Telegraf内置API(推荐)
Telegraf已经封装了Telegram Bot API的调用,用ctx.telegram.getFile()就能直接获取文件信息,不用自己手动写HTTP请求,代码更简洁:
const { Telegraf } = require('telegraf'); const fs = require('fs'); const axios = require('axios'); // 也可以用node-fetch,按需选择 // 替换成你的机器人Token const bot = new Telegraf('YOUR_BOT_TOKEN'); // 监听用户发送的图片 bot.on('photo', async (ctx) => { // 注意:Telegram会发送多分辨率的图片,最后一个元素是最高清的版本,[0]是缩略图 const highestResPhotoId = ctx.message.photo[ctx.message.photo.length - 1].file_id; try { // 获取文件的详细信息(包含file_path) const fileInfo = await ctx.telegram.getFile(highestResPhotoId); // 拼接真正的下载地址 const downloadUrl = `https://api.telegram.org/file/bot${bot.token}/${fileInfo.file_path}`; // 以流的方式下载并保存文件,适合大文件,避免内存溢出 const downloadResponse = await axios({ url: downloadUrl, method: 'GET', responseType: 'stream' }); // 保存到本地,这里可以自定义文件名,比如用Telegram返回的文件名(如果有的话) const savePath = `./downloaded_${Date.now()}.jpg`; const fileWriter = fs.createWriteStream(savePath); downloadResponse.data.pipe(fileWriter); // 监听保存完成事件 fileWriter.on('finish', () => { console.log(`图片已保存到:${savePath}`); ctx.reply('图片下载保存成功啦!'); }); // 监听保存错误事件 fileWriter.on('error', (err) => { console.error('保存文件出错:', err); ctx.reply('哎呀,保存图片时出问题了😥'); }); } catch (error) { console.error('获取文件信息失败:', error); ctx.reply('获取图片信息出错了😢'); } }); // 监听用户发送的普通文件(比如文档、压缩包等) bot.on('document', async (ctx) => { const fileId = ctx.message.document.file_id; const fileName = ctx.message.document.file_name || `file_${Date.now()}`; try { const fileInfo = await ctx.telegram.getFile(fileId); const downloadUrl = `https://api.telegram.org/file/bot${bot.token}/${fileInfo.file_path}`; const downloadResponse = await axios({ url: downloadUrl, method: 'GET', responseType: 'stream' }); const savePath = `./${fileName}`; const fileWriter = fs.createWriteStream(savePath); downloadResponse.data.pipe(fileWriter); fileWriter.on('finish', () => { console.log(`文件已保存到:${savePath}`); ctx.reply('文件下载保存成功啦!'); }); fileWriter.on('error', (err) => { console.error('保存文件出错:', err); ctx.reply('保存文件时出问题了😥'); }); } catch (error) { console.error('获取文件信息失败:', error); ctx.reply('获取文件信息出错了😢'); } }); bot.launch();
方法二:手动调用Telegram API(适合自定义需求)
如果你想自己控制HTTP请求的细节,可以直接调用Telegram的getFile API,再拼接下载链接:
const { Telegraf } = require('telegraf'); const fs = require('fs'); const axios = require('axios'); const bot = new Telegraf('YOUR_BOT_TOKEN'); const BOT_TOKEN = bot.token; bot.on('photo', async (ctx) => { const photoFileId = ctx.message.photo[ctx.message.photo.length - 1].file_id; try { // 第一步:调用getFile API获取file_path const getFileRes = await axios.get(`https://api.telegram.org/bot${BOT_TOKEN}/getFile`, { params: { file_id: photoFileId } }); const file_path = getFileRes.data.result.file_path; const downloadUrl = `https://api.telegram.org/file/bot${BOT_TOKEN}/${file_path}`; // 第二步:下载并保存文件,逻辑和方法一一致 const downloadRes = await axios({ url: downloadUrl, method: 'GET', responseType: 'stream' }); const savePath = `./downloaded_${Date.now()}.jpg`; const writer = fs.createWriteStream(savePath); downloadRes.data.pipe(writer); writer.on('finish', () => { console.log(`图片保存完成:${savePath}`); ctx.reply('图片下载成功!'); }); } catch (err) { console.error('出错了:', err); ctx.reply('操作失败,请重试😢'); } }); bot.launch();
关键注意事项
- 安装依赖:别忘了安装需要的包,执行
npm install telegraf axios(用axios的话),如果用node-fetch就装npm install telegraf node-fetch。 - 文件权限:确保你的Node.js进程有写入本地文件的权限,不然会保存失败。
- 文件名处理:可以用
fileInfo.file_name(如果Telegram返回了文件名)来命名,避免重复;也可以用时间戳来生成唯一文件名。 - 大文件优化:用流(stream)的方式下载大文件,比直接下载到内存更高效,不会导致内存溢出。
内容的提问来源于stack exchange,提问作者tesfalem mesele
相关产品推荐
相关产品推荐

