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

从Google Drive取Blob转Base64调用OpenAI API时的报错问题

问题

我正尝试通过Chat Completion接口将Google Drive中的文件发送至OpenAI API,已完成认证并可列出、获取目标文件,Google API返回的数据格式为Blob。

问题在于,将Blob转换为Base64编码字符串时,Supabase Edge Function抛出RangeError或DOMException。当前代码片段(已完成认证和files.get操作后):

const fileDownload = await driveApi.files.get({
  fileId: 'file_id_string',
  alt: 'media',
});
console.log('file download', fileDownload.data);

const blob: Blob = fileDownload.data;
const arrayBuffer = await blob.arrayBuffer();
const uint8Array = new Uint8Array(arrayBuffer);

// Attempt 1
const charCodeString = String.fromCharCode(...uint8Array); // <-- Fails here
const base64String = btoa(charCodeString);

// Attempt 2
const decodedString = new TextDecoder().decode(uint8Array);
const base64String = btoa(decodedString); // <-- Fails here

// Uncomment once I get the base64String right
// await openai.chat.completions.create({
//   model: 'gpt-4o-mini',
//   response_format: 'json_object',
//   messages: [
//     { role: 'user', content: [{ url: base64String, type: 'image_url' }] },
//   ],
// });

两种尝试对应的错误信息:

# Attempt 1 error message
 RangeError: Maximum call stack size exceeded
    at Object.handler (file:///repos/supabase-personal/supabase/functions/openai/index.ts:32:38)
    at Object.runMicrotasks (ext:core/01_core.js:642:26)
    at processTicksAndRejections (ext:deno_node/_next_tick.ts:39:10)
    at runNextTicks (ext:deno_node/_next_tick.ts:48:3)
    at eventLoopTick (ext:core/01_core.js:175:21)
    at async respond (ext:sb_core_main_js/js/http.js:163:14)

# Attempt 2 error message
DOMException: The string to be encoded contains characters outside of the Latin1 range.
    at new DOMException (ext:deno_web/01_dom_exception.js:116:20)
    at btoa (ext:deno_web/05_base64.js:52:13)
    at Object.handler (file:///repos/supabase-personal/supabase/functions/openai/index.ts:37:26)
    at Object.runMicrotasks (ext:core/01_core.js:642:26)
    at processTicksAndRejections (ext:deno_node/_next_tick.ts:39:10)
    at runNextTicks (ext:deno_node/_next_tick.ts:48:3)
    at eventLoopTick (ext:core/01_core.js:175:21)
    at async respond (ext:sb_core_main_js/js/http.js:163:14)

需要更简便或更优的实现方式将文件转成Base64后发送给OpenAI聊天补全接口。


解决方案

问题原因

  • 尝试1中,String.fromCharCode(...uint8Array)会把Uint8Array的每个元素展开作为参数传递,文件较大时参数数量过多,直接触发调用栈溢出,抛出RangeError。
  • 尝试2中,TextDecoder.decode()将二进制数据解码为UTF-8字符串,但图片等非文本文件的二进制内容包含Latin1范围外的字符,而btoa()仅支持处理Latin1字符,因此抛出DOMException。

正确实现方式

在Supabase Edge Function(基于Deno)环境中,推荐使用以下两种高效方案:

方案1:使用Deno内置Base64编码方法(最优)

const fileDownload = await driveApi.files.get({
  fileId: 'file_id_string',
  alt: 'media',
});

const blob: Blob = fileDownload.data;
const arrayBuffer = await blob.arrayBuffer();
const uint8Array = new Uint8Array(arrayBuffer);

// 直接处理Uint8Array,避免大数组展开
const base64String = Deno.core.encodeBase64(uint8Array);

// 拼接OpenAI要求的data URI格式(需替换为实际文件类型,比如从Google Drive的mimeType提取)
const imageBase64Url = `data:image/png;base64,${base64String}`;

await openai.chat.completions.create({
  model: 'gpt-4o-mini',
  response_format: 'json_object',
  messages: [
    { 
      role: 'user', 
      content: [{ 
        type: 'image_url',
        image_url: {
          url: imageBase64Url
        }
      }] 
    },
  ],
});

方案2:分块处理大文件(兼容无Deno.core环境)

如果Deno.core.encodeBase64不可用,可分块处理Uint8Array,避免一次性展开所有元素:

function uint8ArrayToBase64(uint8Array: Uint8Array): string {
  let base64 = '';
  const chunkSize = 0x8000; // 32KB分块,平衡性能与内存
  for (let i = 0; i < uint8Array.length; i += chunkSize) {
    const chunk = uint8Array.subarray(i, i + chunkSize);
    base64 += btoa(String.fromCharCode(...chunk));
  }
  return base64;
}

// 调用转换函数
const base64String = uint8ArrayToBase64(uint8Array);
// 后续拼接data URI并调用OpenAI API的代码同方案1

关键注意事项

  1. 必须拼接data URI前缀:OpenAI的image_url要求格式为data:image/[类型];base64,[编码内容],需根据文件实际类型替换image/png(比如从Google Drive文件的mimeType字段提取)。
  2. 优先使用Deno内置方法:Deno.core.encodeBase64直接操作二进制数组,性能远高于分块处理,且不会触发调用栈溢出问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:53:10