如何使用 FastAPI UploadFile 将 multitype/form 数据保存到 Python 中的硬文件?

How do you save multitype/form data to a hard file in Python with FastAPI UploadFile?

https://fastapi.tiangolo.com/tutorial/request-files/

*下面解决了*

我得到了一个大小合适的字节数组,但我不确定如何正确解析它以保存收到的表单文件数据。

即将开始工作:

@app.post("/uploadfiles/")
async def create_files(files: List[bytes] = File(...)):
    out_file = open("files/1.txt", "w") # open for [w]riting as [b]inary
    out_file.write( str([(file) for file in files]))
    out_file.close()
    return {"file_sizes": [len(file) for file in files]}

脚本生成的文件不再是可读的 .png。我假设我使用的库不正确,但我不确定从哪个开始:HTMLResponse、FastAPI、multipart 还是 List?关于如何重新正确解析这些字节的任何想法或文档?

编辑

每次休息并回顾 FastAPI 文档后,我发现这个特定的字节数据数组是 multipart/form-data 数据(所以也许我会找到一个 python 库来阅读表格data/images):

这是生成的数据的一个小示例(前 ~100 个字符):

[b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03\xe8\x00\x00\x01\xf4\x08\x06\x00\x00\x00\xae(\x07-\x00\x00\x01\x86iCCPICC profile\x00\x00(\x91}\x91=H\

我做到了!!!

秘密是 python 的原生字节识别库和操作顺序!!

@app.post("/uploadfiles/")
async def create_files(files: bytes = File(...)):
    out_file = open("files/1.jpg", "wb") # open for [w]riting as [b]inary
    out_file.write( bytes([(file) for file in files]))
    out_file.close()

在文件命名系统上仍有工作要做 :) 各位 GL!

编辑 2

由于下面的答案不起作用,我编写了一个文件名附加程序:

@app.post("/uploadfiles/")

async def create_files(files: bytes = File(...)):
    with open('C:/data/sample.txt', 'r', encoding='utf-8') as g:
        data=g.readlines()

    for line in data:
        counter = int(line)
        with open('C:/data/sample.txt', 'w') as f:
            counter = counter + 1
            f.write(str(counter))

    out_file = open("files/" + str(counter) + ".jpg", "wb") # open for [w]riting as [b]inary
    out_file.write( bytes([(file) for file in files]))
    out_file.close()

感谢大家的帮助!快乐黑客:^)

编辑 3

我被告知,我正在 posting 的方法与 FastAPI 结合可能是不正确的做法,因此为了更好地理解这一点,我正在 posting 相关的 javascript posts 到后端:

这是我的 reactjs 表单 post 脚本中的相关代码:

 onSubmit = (e) => {
    e.preventDefault();

    const formData = new FormData();
if (this.state.images != null) {

    var form = document.getElementById("apiupform");
    document.getElementById("apiupform").hidden = true;
    Array.from(this.state.images).forEach((image) => {
      formData.append("files", image);
    });

    axios
      .post(`https://****.com/uploadfiles/`, formData, {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      })

感谢大家对这项工作的帮助。当我发现改进时,我会更新它:)

您可以这样保存上传的文件,

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/upload-file/")
async def create_upload_file(uploaded_file: UploadFile = File(...)):
    file_location = f"files/{uploaded_file.filename}"
    with open(file_location, "wb+") as file_object:
        file_object.write(uploaded_file.file.read())
    return {"info": f"file '{uploaded_file.filename}' saved at '{file_location}'"}

或者,
使用 shutil.copyfileobj(...) 方法可能是一种更有效的方法,

<b>import shutil</b>
from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/upload-file/")
async def create_upload_file(uploaded_file: UploadFile = File(...)):
    file_location = f"files/{uploaded_file.filename}"
    with open(file_location, "wb+") as file_object:
        <b>shutil.copyfileobj(uploaded_file.file, file_object)</b>
    return {"info": f"file '{uploaded_file.filename}' saved at '{file_location}'"}

Swagger 示例

我会使用像 aiofiles 这样的异步库来进行文件操作。

由于您 运行 您的应用程序在 事件循环中 文件写入操作将阻止您的应用程序的整个执行。

import aiofiles


@app.post("/uploadfiles/")
async def create_files(files: bytes = File(...)):
    async with aiofiles.open("files/1.jpg", "wb") as f:
        await f.write(bytes([(file) for file in files]))

这对我有用..

@app.post("/fileUpload/")
def fileUpload(ufile: UploadFile = File(...)):
    s = str(ufile.file.read(), 'utf-8')

    with open(ufile.filename, "w+") as buffer:
        buffer.write(s)