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

JS中向freeimage.host API上传Base64图片报错求助

解决 FreeImage.host 上传的 CORS 错误与参数问题

CORS 错误的根源

JSONPlaceholder 这类公开API会配置CORS响应头(如Access-Control-Allow-Origin: *),允许前端跨域请求。但FreeImage.host的上传API未开启前端跨域支持,浏览器的同源策略会拦截这类请求,你看到的TypeError: Failed to fetch本质就是CORS限制导致的。

API 参数的两个问题

你的代码里存在两个参数相关的错误:

  1. Content-Type 不匹配:FreeImage.host的上传接口接受multipart/form-data格式,而非你设置的application/json,直接传JSON会被接口拒绝。
  2. Base64 格式冗余:FileReader.readAsDataURL()返回的字符串包含data:image/xxx;base64,前缀,而API需要的是纯Base64内容,必须去掉这个前缀。

正确实现方案

方案1:后端代理(推荐,彻底解决CORS)

前端无法绕过浏览器的同源策略,最可靠的方式是通过后端中转请求。以下是Node.js + Express的极简代理示例:

// 后端代理代码
const express = require('express');
const fetch = require('node-fetch');
const cors = require('cors');
const app = express();

app.use(cors());
app.use(express.json());

app.post('/proxy-upload', async (req, res) => {
  try {
    const { apiKey, base64Data } = req.body;
    // 移除Base64前缀
    const pureBase64 = base64Data.replace(/^data:image\/\w+;base64,/, '');
    
    const formData = new FormData();
    formData.append('key', apiKey);
    formData.append('action', 'upload');
    formData.append('source', pureBase64);
    formData.append('format', 'json');

    const apiRes = await fetch('https://freeimage.host/api/1/upload/', {
      method: 'POST',
      body: formData
    });
    const result = await apiRes.json();
    res.json(result);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.listen(3001, () => console.log('Proxy running on port 3001'));

前端修改请求目标为代理接口:

// 前端请求代码修改
fetch('http://localhost:3001/proxy-upload', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    apiKey: '<你的API_KEY>',
    base64Data: e.target.result
  })
})
.then(res => res.json())
.then(data => {
  ThunkableWebviewerExtension.postMessage(data.image.url);
})
.catch(err => {
  ThunkableWebviewerExtension.postMessage(`Upload error: ${err}`);
});

方案2:临时前端参数修正(仅测试用,CORS仍会限制)

如果暂时没有后端,先修正参数格式尝试(但浏览器仍会拦截跨域请求,仅用于验证参数是否正确):

reader.onload = function(e) {
  // ... 图片展示逻辑保持不变 ...

  // 处理Base64前缀
  const pureBase64 = e.target.result.replace(/^data:image\/\w+;base64,/, '');
  const formData = new FormData();
  formData.append('key', '<你的API_KEY>');
  formData.append('action', 'upload');
  formData.append('source', pureBase64);
  formData.append('format', 'json');

  fetch('https://freeimage.host/api/1/upload/', {
    method: 'POST',
    body: formData // 无需手动设置Content-Type,浏览器自动处理
  })
  .then(res => res.json())
  .then(data => {
    ThunkableWebviewerExtension.postMessage(data.image.url);
  })
  .catch(err => {
    ThunkableWebviewerExtension.postMessage(`Upload error: ${err}`);
  });
};

注意事项

  • 务必将<你的API_KEY>替换为真实的FreeImage.host密钥,且不要在前端代码中直接暴露密钥(用后端代理时密钥存在后端,更安全)。
  • 检查图片是否符合FreeImage.host的限制:比如文件大小、支持的格式(JPG/PNG等)。
  • 生产环境中,后端代理需要添加认证、限流等安全措施。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 09:30:43