如何在 FastAPI 中提供静态文件

Chr*_*kou 7 routes pkg-resources static-files python-3.x fastapi

我正在尝试提供 package_docs 目录中的静态文件。当我在浏览器中打开时:

http://127.0.0.1:8001/packages/docs/index.html,页面正在运行。

但是我想打开页面:http : //127.0.0.1 : 8001/packages/docs/

没有源文件。输出是 404 Not Found

app.mount("/packages/docs", 
    StaticFiles(directory=pkg_resources.resource_filename(__name__, 'package_docs')
    ), 
    name="package_docs")

@app.get("/packages/docs/.*", include_in_schema=False)
def root():
    return HTMLResponse(pkg_resources.resource_string(__name__, "package_docs/index.html"))


app.include_router(static.router)
app.include_router(jamcam.router, prefix="/api/v1/cams", tags=["jamcam"])
Run Code Online (Sandbox Code Playgroud)

如何更改我的代码?任何建议都会有所帮助。先感谢您。

Jus*_*loy 12

Starlette 中有一个 html 选项,可以在 FastAPI 中使用。Starlette 文档

这会让你有这样的东西:

app.mount("/site", StaticFiles(directory="site", html = True), name="site")
Run Code Online (Sandbox Code Playgroud)

这会将 /site 解析为 /site/index.html,将 /site/foo/ 解析为 /site/foo/index.html 等。

如果您想以使用“directory = / foo”未处理的方式更改文件夹名称,其他答案可以帮助您重定向,但如果您只想加载关联的 .html 文件,这是最简单的选项。


Yag*_*nci 7

您需要使用 FastAPI 的TemplateResponse(实际上是 Starlette 的):

from fastapi import Request
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates

app.mount("/static", StaticFiles(directory="static"), name="static")

templates = Jinja2Templates(directory="package_docs")

@app.get("/items/{id}")
async def example(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})
Run Code Online (Sandbox Code Playgroud)

Request作为 Jinja2 上下文中键值对的一部分。因此,您还必须将其声明为查询参数。并且您必须指定要使用 Jinja 呈现的 html 文件("your.html", {"request": request})

也可以直接返回 HTMLResponse 使用HTMLResponsefromfastapi.responses

from fastapi.responses import HTMLResponse

@app.get("/items/", response_class=HTMLResponse)
async def read_items():
    return """
    <html>
        <head>
            <title></title>
        </head>
        <body>
        </body>
    </html>
    """
Run Code Online (Sandbox Code Playgroud)

您可以从FastAPI 自定义响应中阅读有关自定义响应的更多信息

  • 这个解决方案可以很好地与 javascript 框架(例如 svelte)配合使用,因为您可以使用 jinja 渲染 index.html,如 `bundle.js?{{bundle_version}}` 页面将是最新的 (2认同)

Sab*_*ani 6

\xe2\x96\xb6\xef\xb8\x8f 1. 您不需要显式创建服务/渲染主页/静态文件夹的路由。当您将目录标记为静态时,它将自动获取第一个参数,在本例中routeapp.mount()it\'s app.mount("/")。所以,当你进入基地urlhttp://127.0.0.1:8000/将获得静态文件。

\n

\xe2\x96\xb6\xef\xb8\x8f 2.类app的实例FastAPI()。是的,您可以在单个 FASTAPI 应用程序中拥有任意数量的实例。

\n

\xe2\x96\xb6\xef\xb8\x8f 3.其他相关任务api_app的实例。FastAPI()api

\n

原因2和3需要是因为如果你想坚持使用app实例,当用户请求url http://127.0.0.1:8000/时,用户将获得静态文件,然后当用户请求http://127.0.0.1:8000/时,用户将获得静态文件/127.0.0.1:8000/hello那么服务器会尝试查找hello里面,但是里面static-folder没有!,最终它会是一个类型响应。这就是为什么需要创建 FastAPI 的另一个实例,并使用前缀(\xe2\x96\xb6\xef\xb8\x8f -> 5) 进行注册,因此每个请求都来自装饰器(\xe2 \x96\xb6\xef\xb8\x8f -> 4) 将被解雇!hellostatic-foldernot-foundapi_app/apihttp://127.0.0.1:8000/api/xx@api_app

\n
\n

instance声明和mount()方法调用顺序很重要。

\n
\n
from fastapi import FastAPI\nfrom fastapi.staticfiles import StaticFiles\nfrom starlette.templating import Jinja2Templates\n\ntemplates = Jinja2Templates(directory=\'homepage-app\')\n\n# for ui\n#  -> 2\napp = FastAPI(title="homepage-app")\n\n# for api\n#  -> 3\napi_app = FastAPI(title="api-app")\n\n# for api and route that starts with "/api" and not static\n#  -> 5\napp.mount("/api", api_app)\n\n# for static files and route that starts with "/"\n#  -> 1\napp.mount("/", StaticFiles(directory="static-folder", html=True), name="static-folder") \n\n# for your other api routes you can use `api_app` instance of the FastAPI\n#  -> 4\n@api_app.get("/hello")\nasync def say_hello():\n    print("hello")\n    return {"message": "Hello World"}\n
Run Code Online (Sandbox Code Playgroud)\n


lsa*_*abi 1

来自文档

第一个“/static”指的是该“子应用程序”将“安装”的子路径。因此,任何以“/static”开头的路径都将由它处理。

这意味着您将目录挂载到http://127.0.0.1:8001/packages/docs/,但是您随后需要在 URL 中指定一个文件,或者像您一样添加一个处理程序。但问题是,由于您首先安装了路径,因此它不会考虑包含部分路径的以下路径。

一种可能是首先指定http://127.0.0.1:8001/packages/docs/的路径,以便由 fastapi 处理,然后挂载该文件夹,提供静态文件。

另外,我会将请求http://127.0.0.1:8001/packages/docs/的用户重定向到http://127.0.0.1:8001/packages/docs/index.html