You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI在Swagger可用但React Native调用Heroku部署接口失败排查

问题修复方案

你遇到的两个报错对应明确的根因:

  • 返回带loc字段的422参数校验错误:React Native端异步时序错误,发请求时imagedata字段为空,FastAPI校验必填参数失败,未进入业务逻辑。
  • 切换multipart/form-data后始终进入异常分支:接口定义为接收JSON格式入参,未适配form-data格式,参数解析直接失败。

React Native端修复

原有代码选图后同时执行base64转码和接口请求,而FileReader转码是异步操作,onloadend回调触发时才会完成imgUrl赋值,不等转码完成就发请求,此时imgUrl还是初始空值。另外readAsDataURL返回的结果带data:image/xxx;base64,前缀,直接传给后端会导致base64解码失败。
修复后代码:

// 封装base64转码为Promise,便于同步等待结果
const getImg = async (imageUrl) => {
  const response = await fetch(imageUrl);
  const imageBlob = await response.blob();
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(imageBlob);
    reader.onloadend = () => {
      // 去除Data URL前缀,仅保留纯base64字符串
      const base64data = reader.result.split(',')[1];
      resolve(base64data);
    };
    reader.onerror = reject;
  });
};

const chooseFromLibrary = async () => {
  try {
    const image = await ImagePicker.openPicker({
      width: 3000,
      height: 4000,
      cropping: false,
    });
    // 等待base64转码完成后再执行后续逻辑
    const base64Str = await getImg(image.path);
    setImgUrl(base64Str);
    // 直接传入转码结果发请求,不依赖state异步更新
    const result = await sendOcrRequest(base64Str);
    console.log('OCR返回结果:', result);
  } catch (err) {
    console.error('流程执行失败:', err);
  }
};

const sendOcrRequest = async (base64Img) => {
  const response = await fetch(
    'https://receipt-ocr-heroku.herokuapp.com/receiptOcr',
    {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        imagedata: base64Img,
      }),
    },
  );
  return response.json();
};

FastAPI端修复

原有代码使用裸except直接吞掉所有异常,无法定位具体错误;同时使用了已被NumPy弃用的np.fromstring方法;未对带前缀的base64字符串做兼容处理。
修复后核心代码:

import cv2
import base64
import numpy as np
from processModule import *
from fastapi import FastAPI, Body, HTTPException
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()

# CORS配置保持全放行即可
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"]
)


@app.post("/receiptOcr")
async def main(imagedata: str = Body(...)):
    try:
        # 兼容处理带Data URL前缀的base64入参
        if ',' in imagedata:
            imagedata = imagedata.split(',')[1]
        img_bytes = base64.b64decode(imagedata)
        # 替换已弃用的fromstring方法
        nparr = np.frombuffer(img_bytes, np.uint8)
        img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
        if img is None:
            raise ValueError("base64解析后不是合法图片")
        
        resize_ratio = 500 / img.shape[0]
        original = img.copy()
        resizeImg = opencv_resize(img, resize_ratio)
        grayImg = cv2.cvtColor(resizeImg, cv2.COLOR_BGR2GRAY)
        ret, binImg = cv2.threshold(
            grayImg, 150, 255, cv2.THRESH_BINARY, cv2.THRESH_OTSU)
        contours, hierarchy = cv2.findContours(
            binImg, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

        largest_contours = sorted(
            contours, key=cv2.contourArea, reverse=True)[:10]
        receipt_contour = get_receipt_contour(largest_contours)

        scanned = wrap_perspective(
            original.copy(), contour_to_rect(receipt_contour, resize_ratio))

        result = bw_scanner(scanned)
        ret, img = cv2.threshold(result, 120, 255, cv2.THRESH_BINARY)
        receiptResize = opencv_resize(img, 0.5)
        wordArr = wordDetectionAndExtraction(receiptResize)
        totalPrice = index_containing_substring(
            wordArr, 'total', 'sub')

        return {"totalPrice": totalPrice}
    except Exception as e:
        # 打印具体错误信息便于排查,不要无差别吞错
        print(f"接口处理异常: {str(e)}")
        return {"totalPrice": '0', "error_msg": str(e)}

其他注意事项

  • 无需修改Content-Type为multipart/form-data,保持application/json即可匹配接口定义。
  • Heroku默认请求体大小上限为30MB,若原图分辨率过高导致base64字符串超长,会请求失败,可适当压缩图片尺寸后再上传。
  • React Native的state更新是异步操作,不要在setState后立刻调用依赖该state值的逻辑,优先通过参数传递即时值,避免时序问题。

内容的提问来源于stack exchange,提问作者random

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 21:54:21