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

开发TripoSR的FastAPI接口时遭遇JSON序列化错误求助

问题分析与解决方案

问题根源

  1. 请求方式错误:原接口使用GET请求,无法高效传输图片文件,应改为POST。
  2. 参数传递错误:调用端将图片字节流直接放入JSON payload,JSON不支持序列化bytes类型,需改用multipart/form-data格式上传文件。
  3. 接口参数类型不匹配:FastAPI接口未正确定义文件上传参数,直接声明PIL.Image.Image无法自动解析上传的文件。
  4. 返回值格式问题:原接口返回{rv}写法错误,若generate返回文件字节或复杂结构,需处理为前端可接收的格式(如base64编码)。

FastAPI接口修正代码

from fastapi import FastAPI, UploadFile, File, Form
from gradio_app import preprocess, generate
from PIL import Image
import io
import base64
from typing import List, Optional

app = FastAPI()

@app.post("/tripo-api")
def generator(
    input_image: UploadFile = File(...),
    do_remove_background: bool = Form(...),
    foreground_ratio: float = Form(...),
    mc_resolution: int = Form(...),
    formats: Optional[List[str]] = Form(default=["obj", "glb"])
):
    """
    生成3D模型的API接口,调用preprocess和generate函数
    """
    # 读取上传的图片并转为PIL.Image
    img_bytes = input_image.file.read()
    pil_img = Image.open(io.BytesIO(img_bytes)).convert("RGB")
    
    # 调用预处理函数
    output_prepr = preprocess(
        input_image=pil_img,
        do_remove_background=do_remove_background,
        foreground_ratio=foreground_ratio
    )
    
    # 调用生成函数
    rv = generate(
        output_prepr,
        mc_resolution=mc_resolution,
        formats=formats
    )
    
    # 将生成的文件转为base64,方便前端接收
    response_data = {}
    # 假设generate返回{格式: 文件字节}的字典,需根据实际返回结构调整
    for fmt, file_bytes in rv.items():
        response_data[fmt] = base64.b64encode(file_bytes).decode("utf-8")
    
    return response_data

调用端修正代码

import requests
import base64

# API endpoint
url = "http://localhost:8000/tripo-api"

# 示例参数
input_image_path = "examples/captured.jpeg"
do_remove_background = True
foreground_ratio = 0.8
mc_resolution = 512
formats = ["obj", "glb"]

# 准备请求数据:文件用files,其他参数用data
files = {"input_image": open(input_image_path, "rb")}
data = {
    "do_remove_background": do_remove_background,
    "foreground_ratio": foreground_ratio,
    "mc_resolution": mc_resolution,
    "formats": formats
}

# 发送POST请求
response = requests.post(url, files=files, data=data)

# 处理响应
if response.status_code == 200:
    print("API请求成功!")
    result = response.json()
    # 示例:将base64转回文件
    for fmt, b64_str in result.items():
        with open(f"output.{fmt}", "wb") as f:
            f.write(base64.b64decode(b64_str))
else:
    print(f"API请求失败,状态码: {response.status_code}")
    print(f"错误信息: {response.text}")

前端适配说明

前端需通过FormData对象上传文件和参数:

  1. 创建包含文件输入框和参数控件的表单
  2. 收集数据并发送请求:
const formData = new FormData();
formData.append("input_image", document.getElementById("image-input").files[0]);
formData.append("do_remove_background", true);
formData.append("foreground_ratio", 0.8);
formData.append("mc_resolution", 512);
formData.append("formats", "obj");
formData.append("formats", "glb");

fetch("http://localhost:8000/tripo-api", {
    method: "POST",
    body: formData
})
.then(response => response.json())
.then(data => {
    // 处理返回的base64数据,下载模型文件
    for (const fmt in data) {
        const blob = b64toBlob(data[fmt], getMimeType(fmt));
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        a.download = `model.${fmt}`;
        a.click();
        URL.revokeObjectURL(url);
    }
})
.catch(error => console.error("请求失败:", error));

// base64转Blob辅助函数
function b64toBlob(b64Data, contentType = "", sliceSize = 512) {
    const byteCharacters = atob(b64Data);
    const byteArrays = [];
    for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        const slice = byteCharacters.slice(offset, offset + sliceSize);
        const byteNumbers = new Array(slice.length);
        for (let i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
        }
        const byteArray = new Uint8Array(byteNumbers);
        byteArrays.push(byteArray);
    }
    return new Blob(byteArrays, { type: contentType });
}

// 获取格式对应MIME类型
function getMimeType(fmt) {
    const mimeMap = {
        "obj": "text/plain",
        "glb": "model/gltf-binary"
    };
    return mimeMap[fmt] || "application/octet-stream";
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 17:44:52