HTML 表单不想发送图像

HTML form doesn't want to send an image

我有一个复杂的任务,现在我不知道事情不能正常工作的原因。

所以我有 2 个服务 - 我的 Django 主服务器和 OCR 服务。 OCR 服务是用 FastAPI 构建的,只获取图像、处理它和 return 的响应作为 JSON 和来自图像的数据。这就是我的 fastapi 文件的样子:

from fastapi import FastAPI, File, UploadFile, Request

import celery_launch
from cleaning_folders import cleaning_folder
from config import save_img_from_form


f_app = FastAPI()

def save_img_from_form(image):
    ts = time.time() * 1000
    digit = random.randint(0, 9)
    file_name = "img_{digit}_{ts}.jpg".format(digit=digit, ts=ts)
    with open(os.path.join('temp_img', file_name), 'wb') as buffer:
        shutil.copyfileobj(image.file, buffer)
    return buffer

@f_app.post("/api/ocr")
async def send_request(image: UploadFile = File(default='Any', media_type='multipart/form-data')):
    buffer = save_img_from_form(image)

    response = celery_launch.ocr_process(
            selected_town='Templates/Chernomorsk',
            raw_img_path=buffer.name,
            selected_billing_type=1
        )

        json_response = response.get()

        cleaning_folder('temp_img')
        return json_response

so save_img_from_form() 从请求中获取一个图像对象,并将其保存到磁盘以供下一步处理。然后 celery 运行s 并完成所有 OCR 处理,然后 returns 一个字典。

因此,当我使用 Swagger UI 作为交互式 API 测试服务时,一切正常,因此在 Swagger UI 中,我可以通过 html 输入和然后单击 运行 我的端点按钮。然后我得到正确的 JSON 作为回应。我还检查了网络 activity(Chrome 中的 ctrl+shift+I)和网络操作,它链接到我的端点我看到很多关于我的请求的东西以及表单数据(图像 ofc) .

但问题在另一个。我需要在我的 Django 服务器上加载图像,然后使用请求库将带有此文件的请求发送到 FastAPI 服务。但是在这里我遇到了很多麻烦。我有这样一个html形式:

<form method="POST" action="{% url 'send_ocr_form' %}" enctype="multipart/form-data">
        {% csrf_token %}
        <input type="hidden" name="pk" value="{{pk}}">
        <input type="file" id="ocr_image" name="ocr_image" accept=".jpg, .jpeg"><br>
        <button type="submit">Recognize</button>
</form>

某些服务内容需要 name="pk" 的隐藏字段。因此,为了加载图像,我有一个名称为“ocr_image”的字段。

我对这个表格的看法是:

def send_ocr_bill_form(request):
    image = request.FILES['ocr_image'].temporary_file_path()

    ocr_response = send_ocr_bill(image=image)
    files = {'file': open(image, 'rb')}
    ocr_response = requests.post('http://127.0.0.1:5005/api/ocr', files=files)
    print(ocr_response.json())

    return redirect(request.META.get('HTTP_REFERER', '/accounts/profile_page/'))

这不是这个视图的全部功能,它只是因为当前的问题而没有结束。

所以当我发送带有图像的表单时 FastAPI 使用 default='Any' 作为图像变量,这意味着请求中没有文件。当我检查网络时,我的请求中也没有看到 'form data' 块。所以好像我不发送图像。但在我看来,我可以轻松地从 request.FILES 获取并打印一个对象,查看它的名称和临时路径,这意味着我加载图像并在我的请求中发送它。

还有一个有趣的事实。当我删除我的文件输入并仅保留 csrf 令牌和 pk 隐藏输入然后提交表单时,在我的网络请求中我可以看到表单数据然后在视图中获取我的“pk”。但是当我return文件输入时,表单数据块消失了。

花了这么多时间来解决这个问题,答案是如此简单。 好吧,我的失败是请求库。 让我们看看我的 FastAPI 端点第一个字符串:

async def send_request(image: UploadFile = File(default='Any', media_type='multipart/form-data')):

所以我将 'image' 定义为 UploadFile 对象,当然我的端点等待请求中的文件,但是当我在 Django 视图中发送图像时,我这样做:

files = {'file': open(image, 'rb')}
ocr_response = requests.post('http://127.0.0.1:5005/api/ocr', files=files)

所以在 'files' 变量中我也使用 'file' 键将图像分配给它。 我需要改变的是:

files = {'image': open(image, 'rb')}
ocr_response = requests.post('http://127.0.0.1:5005/api/ocr', files=files)

现在当 FastAPI 端点收到请求时,它会从正确的位置获取图像参数,然后我可以用它做所有事情。