首页 > 编程问答 >如何在 FastAPI 中手动创建 UploadFile?

如何在 FastAPI 中手动创建 UploadFile?

时间:2024-07-29 06:29:21浏览次数:7  
标签:python fastapi mime-types

背景

我正在尝试为我的 FastAPI 应用程序编写测试。我有一个对象 ImageRecord ,它将图像上传到S3。方法签名如下:

async def upload_image(file: UploadFile, s3_client=None) -> 'ImageRecord':

API 逻辑(即实际的 @app.post 函数)调用此方法来上传对象。我想通过将图像文件上传到 moto - 模拟的 S3 存储桶来测试此方法。此方法在 ImageRecord 中需要一个 UploadFile 因为它是从函数调用的 - 所以我不能只传递字节。此外,我在代码中调用 file.content_type 来获取内容类型。

问题

我无法创建实际API的实例并调用它,因为为了注入模拟的S3对象,我必须直接从 ImageRecord 调用 Python 方法 - 而不是通过 HTTP 请求。但是,这意味着我需要手动创建 UploadFile 对象。以下是我创建它的方法:

contents = open("resc/valid_image.jpg", "rb").read()
upload_file = UploadFile(filename="test_image.jpg", file=io.BytesIO(contents))

但是,当我将其上传到 ImageRecord 时,我收到错误:

Invalid type for parameter ContentType, value: None, type: <class 'NoneType'>, valid types: <class 'str'>

因为 upload_file.content_type None 在真实的API代码中,当FastAPI创建文件时, 源代码 说:

请求的内容类型, 来自标头 但是我手动创建的文件没有标头,并且不接受 content_type 中的 init 参数

.

TL;DR FastAPI.UploadFile 手动创建的 content_type 没有 UploadFile ,因为必须从标头中推断出来。有没有办法用a content_type 创建 UploadFile.content_type 实例来进行测试?或者我是否需要重构我的代码,以便它从内容推断内容类型,并一起跳过


你不需要(也不应该)手动创建 UploadFile 实例来进行测试。 UploadFile 是 FastAPI 内部使用的类,用于处理来自真实的 HTTP 请求的文件。

在你的测试中,你应该直接将字节内容传递给 upload_image 函数,并在函数内部处理内容类型检测。你可以使用 Python 的 mimetypes 模块来根据文件名或字节内容推断内容类型。

以下是更新后的代码示例:

import io
import mimetypes

# ...

async def upload_image(file: bytes, s3_client=None) -> 'ImageRecord':
    """
    Uploads an image to S3.

    Args:
        file: The image file contents as bytes.
        s3_client: An optional boto3 S3 client.
    """
    content_type = mimetypes.guess_type("test_image.jpg")[0] or "application/octet-stream"

    # ... your upload logic using s3_client and content_type ...

# ...

def test_upload_image():
    with open("resc/valid_image.jpg", "rb") as f:
        contents = f.read()
    image_record = asyncio.run(upload_image(contents))
    # ... your assertions ...

在这个例子中:

  1. 我们修改了 upload_image 函数,使其接受 bytes 类型的 file 参数,而不是 UploadFile
  2. 我们使用 mimetypes.guess_type 函数根据文件名推断内容类型。如果无法推断,则默认为 application/octet-stream
  3. 在测试函数中,我们直接读取文件内容并将其作为字节传递给 upload_image 函数。

这种方法有几个优点:

  • 更简洁的测试: 你不需要创建模拟的 UploadFile 对象。
  • 更贴近实际代码: 你的 upload_image 函数现在可以处理来自任何来源的字节内容,而不仅仅是 UploadFile 对象。
  • 更易于维护: 你不需要担心手动设置 UploadFile 对象的属性。

希望这可以帮助你编写更清晰、更有效的测试!

标签:python,fastapi,mime-types
From: 78804949

相关文章

  • Python Discord Bot 的应用程序命令的区域设置名称(多语言别名)
    如何根据用户的语言设置,使应用程序命令的名称具有不同的名称例如,如果一个用户将其discord的语言设置为英语,则用户可以看到英语的应用程序命令名称。另一方面,如果另一个用户将其不和谐语言设置为法语,则用户可以看到法语中的相同应用程序命令的名称。为此,我尝试使用ap......
  • 如何在Python中添加热键?
    我正在为游戏制作一个机器人,我想在按下热键时调用该函数。我已经尝试了一些解决方案,但效果不佳。这是我的代码:defstart():whileTrue:ifkeyboard.is_pressed('alt+s'):break...defmain():whileTrue:ifkeyboard.is_pr......
  • 在Python中解压文件
    我通读了zipfile文档,但不明白如何解压缩文件,只了解如何压缩文件。如何将zip文件的所有内容解压缩到同一目录中?importzipfilewithzipfile.ZipFile('your_zip_file.zip','r')aszip_ref:zip_ref.extractall('target_directory')将......
  • 如何在Python中从RSA公钥中提取N和E?
    我有一个RSA公钥,看起来像-----BEGINPUBLICKEY-----MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAvm0WYXg6mJc5GOWJ+5jkhtbBOe0gyTlujRER++cvKOxbIdg8So3mV1eASEHxqSnp5lGa8R9Pyxz3iaZpBCBBvDB7Fbbe5koVTmt+K06o96ki1/4NbHGyRVL/x5fFiVuTVfmk+GZNakH5dXDq0fwvJyVmUtGYA......
  • Swagger、Docker、Python-Flask: : https://editor.swagger.io/ 生成服务器 python-fl
    在https://editor.swagger.io/上您可以粘贴一些json/yaml。我正在将此作为JSON进行测试(不要转换为YAML):{"swagger":"2.0","info":{"version":"1.0","title":"OurfirstgeneratedRES......
  • 使用 Matplotlib 的 Python 代码中出现意外的控制流
    Ubuntu22.04上的此Python3.12代码的行为符合预期,除非我按q或ESC键退出。代码如下:importnumpyasnp,matplotlib.pyplotaspltfrompathlibimportPathfromcollectionsimportnamedtuplefromskimage.ioimportimreadfrommatplotlib.widgets......
  • 参考 - Python 类型提示
    这是什么?这是与在Python中使用类型提示主题相关的问题和答案的集合。这个问题本身就是一个社区维基;欢迎大家参与维护。这是为什么?Python类型提示是一个不断增长的话题,因此许多(可能的)新问题已经被提出,其中许多甚至已经有了答案。该集合有助于查找现有内容。范......
  • 我的 Python 程序中解决 UVa 860 的运行时错误 - 熵文本分析器
    我正在尝试为UVa860编写一个解决方案,但是当我通过vJudge发送它时,它一直显示“运行时错误”。fromsysimportstdinimportmathdefmain():end_of_input=Falselambda_words=0dictionary={}text_entropy=0relative_entropy=0whilenotend_of_in......
  • Python进度条
    当我的脚本正在执行某些可能需要时间的任务时,如何使用进度条?例如,一个需要一些时间才能完成并在完成后返回True的函数。如何在函数执行期间显示进度条?请注意,我需要实时显示进度条,所以我不知道该怎么办。我需要thread为此吗?我不知道。现在在执行函数......
  • 此 Python 代码给出了超出时间限制的错误。由于其中使用的输入或输出方法而在其中传递
    N=int(input())L1=input()L=L1.split()s=set(L)d={}foreins:d[e]=L.count(e)print(d)max_value=max(d.values())print(max_value)L=list(d.values())print(L)res=L.count(max_value)print(res)/在提供正常输入时,它运行良好,但在提......