我正在使用kotlin
和ktor编写telegram-bot-api的包装。
我遇到了问题-无法找到上传文件的有效方法。
(来自tg bot API docs)
有三种发送文件的方法(照片,贴纸,音频,媒体等):
使用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
发送文件的正确方法是什么?
答案 0 :(得分:1)
好的,我终于找到答案了。修复了makeRequest
功能:
internal suspend inline fun <reified T> makeRequest(token: String, method: TelegramMethod, vararg params: Pair<String, Any?>): T {
try {
val response = client.submitForm<HttpResponse> {
this.method = HttpMethod.Post
url {
protocol = URLProtocol.HTTPS
host = API_HOST
encodedPath = API_PATH_PATTERN.format(token, method.methodName)
}
body = MultiPartFormDataContent(
formData {
params.forEach { (key, value) ->
when (value) {
null -> {}
is MultipartFile -> append(
key,
value.file.inputStream().asInput(),
Headers.build {
append(HttpHeaders.ContentType, value.mimeType)
append(HttpHeaders.ContentDisposition, "filename=${value.filename}")
}
)
is FileId -> append(key, value.fileId)
else -> append(key, value.toString())
}
}
}
)
}
val result = response.receive<String>()
val r = parseTelegramAnswer<T>(response, result)
return r
} catch (e: BadResponseStatusException) {
val answer = mapper.readValue<TResult<T>>(e.response.content.readUTF8Line()!!)
throw checkTelegramError(e.response.status, answer)
}
}