首页 > 解决方案 > 如何解决 Microsoft Bot Framework 中的内容类型错误?

问题描述

我正在使用 Microsoft Bot Builder Python SDK 构建一个机器人。它托管在 Heroku 上,与 Skype 交换文本消息效果很好。但是我遇到了发送文件的问题。该机器人生成一个 JSON 文件并将其发送给用户。我正在使用_get_upload_attachment附件机器人代码的方法(请参阅下面的更改),当机器人在本地运行时,文件将毫无问题地发送到 Bot Framework Emulator。部署到 Heroku 后,文件通过Bot Framework 门户中的测试工具成功发送。但是从 Skype 触发文件发送后,出现如下所示的错误。似乎此错误特定于 Skype 频道。

什么可能引发此错误,我该如何解决?

错误:

2021-02-18T08:28:32.579790+00:00 app[web.1]: [on_turn_error] unhandled error: Operation returned an invalid status code 'Not Found'
2021-02-18T08:28:32.581176+00:00 app[web.1]: Traceback (most recent call last):
2021-02-18T08:28:32.581226+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/botbuilder/core/bot_adapter.py", line 128, in run_pipeline
2021-02-18T08:28:32.581227+00:00 app[web.1]: context, callback
2021-02-18T08:28:32.581229+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/botbuilder/core/middleware_set.py", line 69, in receive_activity_with_status
2021-02-18T08:28:32.581230+00:00 app[web.1]: return await self.receive_activity_internal(context, callback)
2021-02-18T08:28:32.581247+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/botbuilder/core/middleware_set.py", line 79, in receive_activity_internal
2021-02-18T08:28:32.581248+00:00 app[web.1]: return await callback(context)
2021-02-18T08:28:32.581249+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/botbuilder/core/activity_handler.py", line 68, in on_turn
2021-02-18T08:28:32.581250+00:00 app[web.1]: await self.on_message_activity(turn_context)
2021-02-18T08:28:32.581266+00:00 app[web.1]: File "/app/bot.py", line 140, in on_message_activity
2021-02-18T08:28:32.581267+00:00 app[web.1]: reply.attachments = [await self._get_upload_attachment(turn_context)]
2021-02-18T08:28:32.581268+00:00 app[web.1]: File "/app/bot.py", line 426, in _get_upload_attachment
2021-02-18T08:28:32.581269+00:00 app[web.1]: type = "application/json"
2021-02-18T08:28:32.581288+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/botframework/connector/aio/operations_async/_conversations_operations_async.py", line 1138, in upload_attachment
2021-02-18T08:28:32.581289+00:00 app[web.1]: raise models.ErrorResponseException(self._deserialize, response)
2021-02-18T08:28:32.581316+00:00 app[web.1]: botbuilder.schema._models_py3.ErrorResponseException: Operation returned an invalid status code 'Not Found

获取附件方法:

async def _get_upload_attachment(self, turn_context: TurnContext) -> Attachment:
    """
    Creates an "Attachment" to be sent from the bot to the user from an uploaded file.
    :param turn_context:
    :return: Attachment
    """
    with open("/tmp/exports/export.json", "rb") as in_file:
        json_data = in_file.read()
    connector = await turn_context.adapter.create_connector_client(
        turn_context.activity.service_url
    )
    conversation_id = turn_context.activity.conversation.id
    response = await connector.conversations.upload_attachment(
        conversation_id,
        AttachmentData(
            name = "export.json",
            original_base64 = json_data,
            type = "application/json"
        )
    )
    base_uri: str = connector.config.base_url
    attachment_uri = (
        base_uri
        + ("" if base_uri.endswith("/") else "/")
        + f"v3/attachments/{response.id}/views/original"
    )
    return Attachment(
        name = "export.json",
        content_type = "application/json",
        content_url = attachment_uri,
    )

UPD: 我已经用 XLSX 替换了 JSON 导出并面临同样的问题:XLSX 文件已成功发送到Bot Framework 门户中的测试工具(我可以下载并保存),但是“机器人遇到错误或错误. 要继续运行此机器人,请修复机器人源代码。” 消息返回到 Skype 频道。Heroku 日志显示与上述错误示例类似的错误。

机器人发送的文件由建议的操作按钮触发,如下面的屏幕截图所示。

机器人发送的 XLSX 文件

标签: pythonbotframeworkchatbotskypeskype-bots

解决方案


随着调试 Python 代码的经验越来越丰富,您可能会发现 Python 堆栈跟踪中的行号指的是多行函数调用的最后一行,而不是第一行。当您考虑解释器如何从上到下一次读取一行时,这是有道理的,并且它不能调用该函数,直到它知道所有参数是什么。这意味着即使您在堆栈跟踪中看到的行是type = "application/json",这只是因为它是函数调用的最后解释行,因此您应该注意被调用的函数:upload_attachment。您的问题与内容类型无关。

我们可以看到它upload_attachment引发了“未找到”错误。您可能会将其识别为与 404 关联的消息。这意味着您的连接器客户端正在调用的基础REST API 操作对于给定的服务 URL 不存在,这意味着 Skype 通道不支持该操作。这应该不足为奇,因为大多数操作都是特定于通道的。

我尝试以传统方式向 Skype 发送附件,但出现 400 错误:

{
    "error": {
        "code": "BadSyntax",
        "message": "File attachments aren’t supported for this bot"
    }
}

这并没有给我们留下很多选择。如果您真的想在 Skype 中向用户发送文件附件,则必须自己将其上传到某个外部服务器,然后将其 URL 提供给用户。如果您不介意将文件上传到公共 URL,那么这将是最简单的,但如果您希望文件是私有的,那么您需要将其上传到机器人和用户都有凭据的某个安全系统. 那可能会变得复杂。

你可能会对这个答案感到失望,但我不认为你会得到一个更好的答案。Skype 机器人已被弃用一年多,这意味着您不应该期望在您的 Skype 机器人问题上获得任何官方帮助。我的建议是切换到另一个聊天平台,例如 Teams。


推荐阅读