Я пишу оболочку для telegram-bot-api, используя kotlin
и ktor .У меня проблема - не могу найти рабочий способ загрузки файлов.
(из tg bot api docs )
Существует три способа отправки файлов (фотографии,наклейки, аудио, мультимедиа и т. д.):
- Если файл уже хранится где-то на серверах Telegram, его не нужно повторно загружать: каждый объект файла имеет поле file_idпросто передайте этот file_id в качестве параметра вместо загрузки.Для файлов, отправляемых таким способом, ограничений нет.
- Предоставьте Telegram URL-адрес HTTP для отправляемого файла.Telegram загрузит и отправит файл.Максимальный размер 5 МБ для фотографий и 20 МБ для других типов содержимого.
- Разместите файл, используя multipart / form-data, обычным образом, чтобы файлы загружались через браузер.Максимальный размер 10 МБ для фотографий, 50 МБ для других файлов.
С 1-м и 2-м способами у меня нет проблем.
Пока у меня есть эта уродливая функция, которая делает запрос на tg и анализирует ответ:
internal suspend inline fun <reified T> makeRequest(token: String, method: TelegramMethod, vararg params: Pair<String, Any?>, files: Map<String, String> = emptyMap()): T {
try {
val data: List<PartData> = formData {
files.forEach { key, fileName ->
append(key, Files.newInputStream(Paths.get(fileName)).asInput())
}
}
val response = client.submitFormWithBinaryData<HttpResponse>(data) {
this.method = HttpMethod.Post
url {
protocol = URLProtocol("https", 42)
host = API_HOST
encodedPath = API_PATH_PATTERN.format(token, method.methodName)
params.forEach { (name, value) ->
if (value != null) { this.parameters[name] = value as String }
}
}
}
val result = response.receive<String>()
return parseTelegramAnswer<T>(response, result)
} catch (e: BadResponseStatusException) {
val answer = mapper.readValue<TResult<T>>(e.response.content.readUTF8Line()!!)
throw checkTelegramError(e.response.status, answer)
}
}
Без файлов это работает, с файлами - нет.(Я думаю, что я все делаю неправильно)
Пример использования:
suspend fun getUpdates(offset: Long? = null, limit: Int? = null, timeout: Int? = null, allowedUpdates: List<String>? = null): List<Update> =
api.makeRequest(
token,
TelegramMethod.getUpdates,
"offset" to offset?.toString(),
"limit" to limit?.toString(),
"timeout" to timeout?.toString(),
"allowed_updates" to allowedUpdates
)
Я протестировал его на разных файлах и обнаружил, что:
если я отправляю файлы между 17,9 KiB
и 56,6 KiB
, я получаю от tg следующую ошибку: Bad Request: wrong URL host
если я отправляю файлы между 75,6 KiB
и 913,2 KiB
, я получаю ошибку413 Request Entity Too Large
* Я использовал sendDocument
метод
Каков истинный способ отправки файлов с использованием ktor
?