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 参数的两个问题
你的代码里存在两个参数相关的错误:
- Content-Type 不匹配:FreeImage.host的上传接口接受
multipart/form-data格式,而非你设置的application/json,直接传JSON会被接口拒绝。 - 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
相关产品推荐
相关产品推荐

