Fastapi UploadFile 检查幻数

Fastapi UploadFile check magic numbers

我正在尝试验证表单数据 post 上的文件类型(仅允许 PDF)。我试过使用 filetypepuremagic 库,每个库似乎都被 fastapi 通过 UploadFile 发送的 SpooledTemporaryFile 窒息了。到目前为止,我有以下代码。有什么方法可以使用 SpooledTemporaryFile 通过幻数检查传入文件是 PDF:

from fastapi import FastAPI, Request, File, UploadFile
import puremagic


app = FastAPI()

@app.post('/')
async def read_root(request: Request, file: UploadFile = File(...)):
    ext = puremagic.from_stream(file.file, mime=True, filename=file.filename)
    return {"msg": ext}

输出

[2021-08-09 20:22:17 -0400] [18776] [INFO] Running on http://127.0.0.1:8000 (CTRL + C to quit)
[2021-08-09 20:22:28 -0400] [18776] [ERROR] Error in ASGI Framework
Traceback (most recent call last):
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\hypercorn\asyncio\context.py", line 39, in _handle
    await invoke_asgi(app, scope, receive, send)
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\hypercorn\utils.py", line 239, in invoke_asgi
    await app(scope, receive, send)
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\fastapi\applications.py", line 208, in __call__
    await super().__call__(scope, receive, send)
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\starlette\applications.py", line 112, in __call__
    await self.middleware_stack(scope, receive, send)
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
    raise exc from None
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\starlette\exceptions.py", line 82, in __call__
    raise exc from None
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\starlette\exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\starlette\routing.py", line 580, in __call__
    await route.handle(scope, receive, send)
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\starlette\routing.py", line 241, in handle
    await self.app(scope, receive, send)
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\starlette\routing.py", line 52, in app
    response = await func(request)
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\fastapi\routing.py", line 219, in app
    raw_response = await run_endpoint_function(
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\fastapi\routing.py", line 152, in run_endpoint_function
    return await dependant.call(**values)
  File ".\app\main.py", line 10, in read_root
    ext = puremagic.from_stream(file.file, mime=True, filename=file.filename)  
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\puremagic\main.py", line 215, in from_stream
    return _magic(head, foot, mime, ext)
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\puremagic\main.py", line 117, in _magic
    info = _identify_all(header, footer, ext)[0]
  File "c:\python38\.virtualenvs\testfastapijinja2-dk7jcx6p-py3.8\lib\site-packages\puremagic\main.py", line 108, in _identify_all
    raise PureError("Could not identify file")
puremagic.main.PureError: Could not identify file

想通了。代码如下。我将 SpoolTemp 文件转换为 NamedTemporaryFile。

@app.post('/')
async def read_root(request: Request, file: UploadFile = File(...)):

    pdf_file = NamedTemporaryFile(delete=False)
    pdf_file.write(file.file.read(3000))
    pdf_file.close()
    ext = puremagic.from_file(pdf_file.name)
    os.unlink(pdf_file.name)
    print(ext)