无法通过路径加载,如何用THREE.js加载原始GLTF文件?
加载原始GLTF字符串(无需文件路径)
手里有原始GLTF字符串,无法通过文件路径加载,尝试三种方法均报错,以下是问题分析和正确解决方案:
原始GLTF字符串示例
const rawGltf = '{"asset" : {"generator" : "Khronos glTF Blender I/O v3.2.43","version" : "2.0"},"scene" : 0,"scenes" : [...}'
三种错误尝试的问题分析
1. 错误的base64二次转换
const dataURL = "data:model/gltf+json;base64," + Buffer.from(rawGltf, "base64").toString("base64"); const gltf = useLoader(GLTFLoader, dataURL);
报错:Uncaught Could not load data:...: Unexpected token 'j', "j���z���"... is not valid JSON
- 原因:
Buffer.from(rawGltf, "base64")错误地把原始JSON字符串当成base64解码,再重新编码后内容完全损坏,导致JSON解析失败。
2. 直接拼接原始字符串到base64段
const dataURL = "data:model/gltf+json;base64," + rawGltf; const gltf = useLoader(GLTFLoader, dataURL);
报错:Uncaught Could not load data:...: Failed to fetch
- 原因:dataURL的base64部分必须是经过base64编码的内容,直接放原始JSON不符合格式,加载器无法识别。
3. 使用btoa但未处理Unicode/二进制缓冲区
const GeneratePrimitiveObj = (obj: any) => { const dataURL = "data:model/gltf+json;base64," + btoa(obj); const gltf = useLoader(GLTFLoader, dataURL); return gltf; }; <primitive object={GeneratePrimitiveObj(JSON.stringify(objects[0]["obj_json"])).scene} scale={0.8} />
报错:Failed to load buffer "data:application/octet-stream;base64,AACAPwAAgD8AAIC/AAC...
- 原因:
btoa无法处理Unicode字符,且直接编码包含内嵌二进制缓冲区的GLTF JSON时,会破坏缓冲区的base64编码结构,导致加载失败。
正确解决方案
方法一:Blob + ObjectURL(推荐,支持所有GLTF类型)
这种方法无需处理base64,直接将字符串包装为Blob生成临时URL,兼容性和可靠性最高:
import { useLoader, useEffect } from '@react-three/fiber'; import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; // 假设rawGltf是你的原始GLTF JSON字符串 const blob = new Blob([rawGltf], { type: 'model/gltf+json' }); const url = URL.createObjectURL(blob); const gltf = useLoader(GLTFLoader, url); // 组件卸载时释放URL,避免内存泄漏 useEffect(() => { return () => URL.revokeObjectURL(url); }, [url]); // 使用场景 return <primitive object={gltf.scene} scale={0.8} />;
方法二:正确的base64编码(仅适用于纯JSON内嵌缓冲区的GLTF)
如果你的GLTF没有外部依赖,所有二进制数据都已内嵌为base64,可使用正确的UTF-8编码方式生成dataURL:
import { useLoader } from '@react-three/fiber'; import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; // 处理Unicode字符,先转UTF-8字节再编码 const utf8Encoder = new TextEncoder(); const utf8Bytes = utf8Encoder.encode(rawGltf); const base64Str = btoa(String.fromCharCode(...utf8Bytes)); const dataURL = `data:model/gltf+json;base64,${base64Str}`; const gltf = useLoader(GLTFLoader, dataURL); return <primitive object={gltf.scene} scale={0.8} />;
内容的提问来源于stack exchange,提问作者k K
相关产品推荐
相关产品推荐

