如何使用Python请求和FastAPI发送base64图像?

mwkjh3gx  于 2023-02-17  发布在  Python
关注(0)|答案(1)|浏览(212)

我正在尝试基于FastAPI编写一个图像风格转换的代码,我发现将图像的字节转换为base64并传输是非常有效的。
因此,我设计了我的客户端代码,将图像编码为base64字符串并发送到服务器,服务器成功地接收到了它,但是,我在将图像字节恢复到ndarray时遇到了一些困难。
我得到以下错误:

image_array = np.frombuffer(base64.b64decode(image_byte)).reshape(image_shape)

ValueError: cannot reshape array of size 524288 into shape (512,512,4)

这是我的客户代码:

import base64
import requests
import numpy as np
import json
from matplotlib.pyplot import imread
from skimage.transform import resize

if __name__ == '__main__':
    path_to_img = "my image path"

    image = imread(path_to_img)
    image = resize(image, (512, 512))

    image_byte = base64.b64encode(image.tobytes())
    data = {"shape": image.shape, "image": image_byte.decode()}

    response = requests.get('http://127.0.0.1:8000/myapp/v1/filter/a', data=json.dumps(data))

这是我的服务器代码:

import json
import base64
import uvicorn
import model_loader
import numpy as np

from fastapi import FastAPI
from typing import Optional

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

@app.get("/myapp/v1/filter/a")
async def style_transfer(data: dict):
    image_byte = data.get('image').encode()
    image_shape = tuple(data.get('shape'))
    image_array = np.frombuffer(base64.b64decode(image_byte)).reshape(image_shape)

if __name__ == '__main__':
    uvicorn.run(app, port='8000', host="127.0.0.1")
9avjhtql

9avjhtql1#

选项1

如前所述,在这里以及here中,用户应该使用UploadFile,以便从客户端应用上传文件(对于async读/写,请查看this answer)。

    • 服务器端:**
@app.post("/upload")
def upload(file: UploadFile = File(...)):
    try:
        contents = file.file.read()
        with open(file.filename, 'wb') as f:
            f.write(contents)
    except Exception:
        return {"message": "There was an error uploading the file"}
    finally:
        file.file.close()
        
    return {"message": f"Successfuly uploaded {file.filename}"}
    • 客户端:**
import requests

url = 'http://127.0.0.1:8000/upload'
file = {'file': open('images/1.png', 'rb')}
resp = requests.post(url=url, files=file) 
print(resp.json())

选项2

但是,如果您仍然需要发送base64编码的图像,您可以按照前面介绍的here(选项2)进行操作。在客户端,您可以将图像编码为base64,然后使用POST请求发送,如下所示:

    • 客户端:**
import base64
import requests

url = 'http://127.0.0.1:8000/upload'
with open("photo.png", "rb") as image_file:
    encoded_string = base64.b64encode(image_file.read())
    
payload ={"filename": "photo.png", "filedata": encoded_string}
resp = requests.post(url=url, data=payload)

在服务器端,您可以使用Form字段接收图像,并按如下方式解码图像:

    • 服务器端:**
@app.post("/upload")
def upload(filename: str = Form(...), filedata: str = Form(...)):
    image_as_bytes = str.encode(filedata)  # convert string to bytes
    img_recovered = base64.b64decode(image_as_bytes)  # decode base64string
    try:
        with open("uploaded_" + filename, "wb") as f:
            f.write(img_recovered)
    except Exception:
        return {"message": "There was an error uploading the file"}
        
    return {"message": f"Successfuly uploaded {filename}"}

相关问题