【问题标题】:FastAPI/Starlette, Web UI: Save File Dialog, Open File DialogFastAPI/Starlette,Web UI:保存文件对话框,打开文件对话框
【发布时间】:2021-11-18 18:34:03
【问题描述】:

我一直在研究这个例子project。非常简明扼要,而且还有一个惊喜:保存文件对话框(标准桌面文件对话框,从 Chrome 打开)。

负责人代码:

src/html.py:

@app.post('/download')
def form_post(request: Request, num: int = Form(...), multiply_by_2: bool = Form(False), action: str = Form(...)):
    if action == 'convert':
        result = spell_number(num, multiply_by_2)
        return templates.TemplateResponse('download.html', context={'request': request, 'result': result, 'num': num})
    elif action == 'download':
        # Requires aiofiles
        result = spell_number(num, multiply_by_2)
        filepath = save_to_text(result, num)
        return FileResponse(filepath, media_type='application/octet-stream', filename='{}.txt'.format(num))

templates/download.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Sample Form</title>
</head>
<body>
<form method="post">
    <input type="number" name="num" value="{{ num }}"/>
    <input type="checkbox" id="multiply_by_2" name="multiply_by_2" value="True">
    <label for="multiply_by_2">Multiply by 2&nbsp;</label>
    <input type="submit" name="action" value="convert">
    <input type="submit" name="action" value="download">
</form>
<p>Result: {{ result }}</p>
</body>
</html>

我在FileResponse文件对话框 上看不到任何提示,更不用说弹出的保存文件对话框。顺便说一句,我也想要打开文件对话框。我试图研究它,但没有成功。

它是如何工作的?

UPD,让自己更清楚。

我正在玩这样的东西:

from tkinter import Tk
from tkinter.filedialog import askopenfilename
...
@app.post("/open")
def form_post(
    request: Request,
    action: str = Form("open"),
):
    if action == "open":
        root = Tk()
        root.withdraw()
        # ensure the file dialog pops to the top window
        root.wm_attributes('-topmost', 1)
        fname = askopenfilename(parent=root)
        print(f"Chosen file: {fname}")
        return templates.TemplateResponse("open.html", context={"request": request})
    elif action == "save":
        # Requires aiofiles
        return FileResponse(
            "templates/legacy/download.html",
            media_type="text/html",
            filename="download.html",
        )

目前,按钮save 使用系统保存文件对话框,而按钮open 使用tkinter 的打开对话框。它会做,因为整个事情只是一个带有 Web UI 的应用程序。不过,它看起来和感觉有点荒谬。

有没有办法让浏览器为打开文件拨号提供服务?

【问题讨论】:

    标签: python fastapi starlette


    【解决方案1】:

    文件对话框是 Chrome 针对这种响应显示的 (application/octet-stream)。服务器端框架不负责创建保存文件对话框;它只是提供一个响应,而浏览器会执行它通常对那种响应所做的事情。

    您可以在响应中使用 Content-Disposition 标头向浏览器指示它应该显示下载对话框而不是直接显示内容(如果它本身支持 mime 类型)。 Content-Disposition 标头还允许您为保存对话框提供默认文件名(但只有文件名 - 不是路径)。

    使用&lt;input type="file" name="name_matching_fastapi_parameter"&gt; 将负责打开文件对话框。你 can then tell FastAPI that you expect that a parameter is a fileUploadFile 类型。

    来自 FastAPI 参考:

    from fastapi import FastAPI, File, UploadFile
    
    app = FastAPI()
    
    
    @app.post("/files/")
    async def create_file(file: bytes = File(...)):
        return {"file_size": len(file)}
    
    
    @app.post("/uploadfile/")
    async def create_upload_file(file: UploadFile = File(...)):
        return {"filename": file.filename}
    

    【讨论】:

    • 非常感谢@MatsLindh!所以application/octet-stream 导致保存文件对话框。非常抱歉,我找不到会导致 打开文件对话框 的 MIME 类型。有这种类型吗?
    • 我看到 MIME 类型只负责文件类型(应该如此)。我仍然看不到如何订购 打开文件对话框
    • 这将是您在 HTML 中执行的操作;当用户单击input type="file" 元素上的“浏览”按钮时,将打开一个文件选择对话框。您不能从您的 FastAPI 代码中执行此操作;它必须在 HTML 本身中完成。
    • 我将&lt;input type="file" name="action" value="name"&gt; 放入模板中,打开对话框就可以了。不过,我无法收集文件名。令人惊讶的是,如何操作信息,尤其是与 FastAPI 相关的信息很少。
    • 如果您查看the page for UploadFile as reference in the answer,您会发现它公开了一个filename 属性: filename: 带有上传的原始文件名的str(例如myimage.jpg) .
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多