我有一个FastAPI端点/image/ocr,它接受、处理和返回多个图像作为StreamingResponse:

async def streamer(images):
    for image in images:
        # Bytes
        image_bytes = await image.read()

        # PIL PNG
        image_data = Image.open(BytesIO(image_bytes))

        # Process
        # image_processed = ...
    
        # Convert from PIL PNG to JPEG Bytes
        image_ocr = BytesIO()

        image_ocr.save(image_processed, format='JPEG')

        yield image_ocr.getvalue()

@router.post('/ocr', summary='Process images')
async def ocr(images: List[UploadFile]):
    return StreamingResponse(
        streamer(images),
        status_code=status.HTTP_200_OK,
        media_type='image/jpeg'
    )

在我的React应用程序中,我使用配置为arraybuffer的Axios将多个图像发送到/image/ocr端点,并使用btoaString.fromCharCodeUnit8Array将返回的图像转换为Base64:

const imageSubmit = async data => {
    const formData = new FormData()
    
    // A `useRef` that stores the uploaded images
    data?.current?.files?.successful.map(image =>
        formData.append('images', image.data)
    )

    try {
        const response = await request.post(
            '/image/ocr',
            formData,
            {responseType: 'arraybuffer'}
        )

        const base64String = btoa(
            String.fromCharCode(
                ...new Uint8Array(response.data)
            )
        )

        const contentType = response.headers['content-type']

        const fullBase64String = `data:${contentType};base64,${base64String}`

        return fullBase64String
    } catch (error) {
        // Error log
    }
}

问题是我发送了多个图像,例如this imagethis image,端点/image/ocr正在接受、处理和返回这些图像,但当我使用最后一个代码片段中的方法转换response.data时,我只得到一个Base64图像.

我看了看原始的response,看看我是否可以迭代通过response.dataArrayBuffer:

Array Buffer object

但它不适用于for(const image of response.data) {}.我看到ArrayBuffer有一个slice方法,但我不确定这是否意味着两个图像都在ArrayBuffer中,我需要切片然后转换,这很奇怪,因为到目前为止,至少有一个图像正在被转换为Base64,或者因为我看到它可以用一些不同的方式完成,所以它被转换为另一种类型here,herehere.

如果slice选项是正确的,我不确定如何 Select 开始和结束,因为ArrayBuffer中的值只是随机数字和符号.

你知道如何在我的Reaction应用程序上同时获得Base64英寸的两张图像吗?

推荐答案

经过几个小时的研究,我放弃了Axios,因为documentation说它"从浏览器生成XMLHttpRequest",这意味着它不支持流.

我阅读了更多关于Streams API的内容,并在Youtube上观看了谷歌的一个系列节目,于是我开始使用Fetch API,因为它支持流媒体写作(16:26)和阅读(6:24).

将我问题中的try块替换为:

const response = await fetch('http://localhost:4000/image/ocr', {
    method: 'POST',
    headers: {
        Authorization: ''
    },
    body: formData
})

const reader = response.body.getReader()

while (true) {
    const { value, done } = await reader.read()

    // Base64
    const base64 = `data:${response.headers['content-type']};base64,${btoa(String.fromCharCode(...new Uint8Array(value)))}`

    console.log(base64)

    if (done) break
}

我能够将异步生成器与StreamingResponse一起使用,并在我的Reaction应用程序中获得多个图像.

深入研究流API是值得的,因为它也可以作为WebSocket工作,而不必编写处理套接字的特定后端

Javascript相关问答推荐

使用Angular 17计算从生日日期起的年、月、天

在JavaScript中使用setProperty方法试图修改css元素值时,我遇到错误

Python类实现的JavaScript吊坠是什么样子的?

无法在page. evalve()内部使用外部函数

在NextJS中使用计时器循环逐个打开手风琴项目?

创建私有JS出口

基于变量切换隐藏文本

我不知道为什么setwritten包装promise 不能像我预期的那样工作

按下同意按钮与 puppeteer 师

配置WebAssembly/Emscripten本地生成问题

无法检测卡片重叠状态的问题

如何将Cookie从服务器发送到用户浏览器

检索相加到点的子项

当我try 将值更改为True时,按钮不会锁定

在VS代码上一次设置多个变量格式

将对象推送到数组会导致复制

如何在HTMX提示符中设置默认值?

从逗号和破折号分隔的给定字符串中查找所有有效的星期几

WebSocketException:远程方在未完成关闭握手的情况下关闭了WebSocket连接.&#三十九岁;

为列表中的项目设置动画