Swift(Vapor)下Telegram API发送文档失败及大文件发送咨询
问题描述
在Linux服务器上使用Swift结合Vapor框架开发Telegram Bot时,执行以下代码尝试通过URL发送文档:
代码片段
let handler16 = TGMessageHandler(filters: .regexp(pattern: "^11$")) {update, bot in if let id = update.message?.chat.id { let chatId: TGChatId = .chat(id) // let file = File(data: "hello", filename: "МЭСК.docx") let params: TGSendDocumentParams = .init(chatId: chatId, document: .url("http://www.ncbi.nlm.nih.gov/geo/download/?acc=GSE46130&format=file")) try bot.sendDocument(params: params) } }
错误信息
Type: server Description: Response marked as
not Ok, it seems something wrong with request
Code: 400
Bad Request: failed to get HTTP URL contentReason:
现咨询如何正确保存并发送自有大文档,已知Telegram服务器上的文件可通过FileInfo.fileId("file_id")发送且无限制,但不清楚自有大文件的处理方式。
解决方案
一、URL发送失败的原因
你使用的NCBI链接大概率存在以下问题,导致Telegram服务器无法正常获取内容:
- 链接带有反爬机制或需要身份验证,Telegram的请求被拦截
- 链接返回的内容不是标准可识别的文档格式
- 链接跳转逻辑复杂,Telegram无法正确解析
二、自有大文件的正确处理方式
针对自有大文件(通常指超过Telegram直接上传限制的文件,一般为50MB以上,以官方API规则为准),可按以下方式处理:
1. 本地文件直接上传(中等大小文件适用)
如果文件在Telegram直接上传限制内(50MB以内),可直接读取服务器本地文件构造File对象发送:
let handler16 = TGMessageHandler(filters: .regexp(pattern: "^11$")) {update, bot in guard let id = update.message?.chat.id else { return } let chatId: TGChatId = .chat(id) // 读取服务器本地的目标文件 guard let fileURL = URL(fileURLWithPath: "/path/to/your/large/document.docx"), let fileData = try? Data(contentsOf: fileURL) else { // 处理文件读取失败的逻辑 return } let file = File(data: fileData, filename: "custom_document_name.docx") let params = TGSendDocumentParams(chatId: chatId, document: .file(file)) try bot.sendDocument(params: params) }
2. 分片上传(超大文件适用)
如果文件超过直接上传限制,需使用Telegram的分片上传API(uploadFile接口),步骤如下:
- 将大文件分割为若干5MB以内的分片(建议每个分片5MB)
- 依次上传每个分片,获取对应上传凭证
- 所有分片上传完成后,调用
sendDocument组合分片信息完成发送
3. 上传一次复用file_id(最高效方案)
无论文件大小,可先将自有文件上传到Telegram服务器一次,获取对应的file_id,之后即可通过FileInfo.fileId无限制复用发送:
// 首次上传获取file_id(可在Bot初始化或单独脚本中执行) let testChatId: TGChatId = .chat(your_test_chat_id) let fileURL = URL(fileURLWithPath: "/path/to/your/large/file")! let fileData = try Data(contentsOf: fileURL) let file = File(data: fileData, filename: "large_file.docx") let uploadParams = TGSendDocumentParams(chatId: testChatId, document: .file(file)) let uploadResponse = try bot.sendDocument(params: uploadParams) let savedFileId = uploadResponse.result?.document?.fileId ?? "" // 将此file_id持久化存储 // 后续发送直接使用file_id let handler16 = TGMessageHandler(filters: .regexp(pattern: "^11$")) {update, bot in guard let id = update.message?.chat.id else { return } let chatId: TGChatId = .chat(id) let params = TGSendDocumentParams(chatId: chatId, document: .fileId(savedFileId)) try bot.sendDocument(params: params) }
注意事项
- 确保Linux服务器上的目标文件有可读权限,避免读取失败
- 分片上传需严格遵循Telegram API的分片规则,否则会上传失败
- 持久化存储
file_id时,建议存入数据库或配置文件,避免重复上传
内容的提问来源于stack exchange,提问作者Pablo Juan
相关产品推荐
相关产品推荐

