在这里,让我们来看看 Frappe 中响应是如何构建的,以及你如何在你的
Frappe 应用或脚本中使用它们。
如果你已经阅读过路由器
文档,你可能已经注意到 Frappe 内部用来根据内容类型
构建响应的 build_response 函数。定义此行为的逻辑属于
frappe.utils.response
模块的一部分,其中 build_response 是该模块的核心内容。
def build_response(response_type=None):
if "docs" in frappe.local.response and not frappe.local.response.docs:
del frappe.local.response["docs"]
response_type_map = {
"csv": as_csv,
"txt": as_txt,
"download": as_raw,
"json": as_json,
"pdf": as_pdf,
"page": as_page,
"redirect": redirect,
"binary": as_binary,
}
return response_type_map[frappe.response.get("type") or response_type]()
上面的代码片段展示了 build_response 的当前实现,
它映射了不同的函数,这些函数充当不同内容类型的处理器。
让我们更深入地了解一下 Frappe v13 中针对 “download”
response_type 的响应处理器。
def as_raw():
response = Response()
response.mimetype = (
frappe.response.get("content_type")
or mimetypes.guess_type(frappe.response["filename"])[0]
or "application/unknown"
)
response.headers["Content-Disposition"] = (
f'{frappe.response.get("display_content_as", "attachment")};'
f' filename="{frappe.response["filename"].replace(" ", "_")}"'
).encode("utf-8")
response.data = frappe.response["filecontent"]
return response
根据 Content-Disposition 头的值,
接收响应的浏览器可能会有不同的行为。如果未设置,该值默认为
“attachment”。
如果 frappe.response.display_content_as 设置为 “inline”,则表示
内容预期在浏览器中内联显示,即作为
网页或网页的一部分显示,而 “attachment” 则表示内容
将被下载并保存在本地。
要创建一个可以直接下载所需文件的 API 端点,
你可以编写类似以下代码来实现直接下载文件。
@frappe.whitelist()
def download(name):
file = frappe.get_doc("File", name)
frappe.response.filename = file.file_name
frappe.response.filecontent = file.get_content()
frappe.response.type = "download"
frappe.response.display_content_as = "attachment"