Feat: upload 接口允许跨域

This commit is contained in:
MarSeventh
2025-06-12 16:50:11 +08:00
parent df1b2282aa
commit afee9d49aa
2 changed files with 67 additions and 34 deletions

View File

@@ -119,20 +119,26 @@
## 最近更新
Add Features:
- `upload`接口支持跨域访问和调用
Fix Bugs:
- 修复`list`接口返回数据完整性的问题
<details>
<summary>更新日志</summary>
## 2025.6.12
Add Features:
- `upload`接口支持跨域访问和调用
Fix Bugs:
- 修复`list`接口返回数据完整性的问题
@@ -1070,10 +1076,14 @@ Web端在登录页面输入你的**认证码**即可登录使用API端需要
# 8.Star History
[![Star History Chart](https://api.star-history.com/svg?repos=MarSeventh/CloudFlare-ImgBed,MarSeventh/Sanyue-ImgHub&type=Date)](https://star-history.com/#MarSeventh/CloudFlare-ImgBed&MarSeventh/Sanyue-ImgHub&Date)
**如果觉得项目不错希望您能给个免费的star✨✨✨非常感谢**
---
[![Star History Chart](https://api.star-history.com/svg?repos=MarSeventh/CloudFlare-ImgBed,MarSeventh/Sanyue-ImgHub&type=Date)](https://star-history.com/#MarSeventh/CloudFlare-ImgBed&MarSeventh/Sanyue-ImgHub&Date)
# 9.Special Sponsors
- **[亚洲云](https://www.asiayun.com/)**:提供云计算服务资源支持(高防服务器|服务器租用|福州高防|广东电信|香港服务器|美国服务器|海外服务器)
- **DartNode**:提供云计算服务资源支持
[![Powered by DartNode](https://dartnode.com/branding/DN-Open-Source-sm.png)](https://dartnode.com "Powered by DartNode - Free VPS for Open Source")

View File

@@ -8,15 +8,30 @@ let securityConfig = {};
let rightAuthCode = null;
let moderateContentApiKey = null;
// 统一的跨域响应创建函数
function createResponse(body, options = {}) {
const defaultHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST',
'Access-Control-Allow-Headers': 'Content-Type, Authorization, authCode',
};
return new Response(body, {
...options,
headers: {
...defaultHeaders,
...options.headers
}
});
}
function UnauthorizedException(reason) {
return new Response(reason, {
return createResponse(reason, {
status: 401,
statusText: "Unauthorized",
headers: {
"Content-Type": "text/plain;charset=UTF-8",
// Disables caching by default.
"Cache-Control": "no-store",
// Returns the "Content-Length" header for HTTP HEAD requests.
"Content-Length": reason.length,
},
});
@@ -89,7 +104,7 @@ export async function onRequestPost(context) { // Contents of context object
// 判断上传ip是否被封禁
const isBlockedIp = await isBlockedUploadIp(env, uploadIp);
if (isBlockedIp) {
return new Response('Error: Your IP is blocked', { status: 403 });
return createResponse('Error: Your IP is blocked', { status: 403 });
}
// 获取IP地址
const ipAddress = await getIPAddress(uploadIp);
@@ -129,7 +144,7 @@ export async function onRequestPost(context) { // Contents of context object
// img_url 未定义或为空的处理逻辑
if (typeof env.img_url == "undefined" || env.img_url == null || env.img_url == "") {
return new Response('Error: Please configure KV database', { status: 500 });
return createResponse('Error: Please configure KV database', { status: 500 });
}
// 获取文件信息
@@ -140,7 +155,7 @@ export async function onRequestPost(context) { // Contents of context object
const fileSize = (formdata.get('file').size / 1024 / 1024).toFixed(2); // 文件大小单位MB
// 检查fileType和fileName是否存在
if (fileType === null || fileType === undefined || fileName === null || fileName === undefined) {
return new Response('Error: fileType or fileName is wrong, check the integrity of this file!', { status: 400 });
return createResponse('Error: fileType or fileName is wrong, check the integrity of this file!', { status: 400 });
}
fileName = fileName.split('/').pop();
@@ -281,7 +296,7 @@ async function tryRetry(err, env, uploadChannel, formdata, fullId, metadata, fil
}
}
return new Response(JSON.stringify(errMessages), { status: 500 });
return createResponse(JSON.stringify(errMessages), { status: 500 });
}
@@ -289,12 +304,12 @@ async function tryRetry(err, env, uploadChannel, formdata, fullId, metadata, fil
async function uploadFileToCloudflareR2(env, formdata, fullId, metadata, returnLink, originUrl) {
// 检查R2数据库是否配置
if (typeof env.img_r2 == "undefined" || env.img_r2 == null || env.img_r2 == "") {
return new Response('Error: Please configure R2 database', { status: 500 });
return createResponse('Error: Please configure R2 database', { status: 500 });
}
// 检查 R2 渠道是否启用
const r2Settings = uploadConfig.cfr2;
if (!r2Settings.channels || r2Settings.channels.length === 0) {
return new Response('Error: No R2 channel provided', { status: 400 });
return createResponse('Error: No R2 channel provided', { status: 400 });
}
const r2Channel = r2Settings.channels[0];
@@ -319,16 +334,18 @@ async function uploadFileToCloudflareR2(env, formdata, fullId, metadata, returnL
metadata: metadata,
});
} catch (error) {
return new Response('Error: Failed to write to KV database', { status: 500 });
return createResponse('Error: Failed to write to KV database', { status: 500 });
}
// 成功上传将文件ID返回给客户端
return new Response(
return createResponse(
JSON.stringify([{ 'src': `${returnLink}` }]),
{
status: 200,
headers: { 'Content-Type': 'application/json' }
headers: {
'Content-Type': 'application/json',
}
}
);
}
@@ -344,7 +361,7 @@ async function uploadFileToS3(env, formdata, fullId, metadata, returnLink, origi
: s3Channels[0];
if (!s3Channel) {
return new Response('Error: No S3 channel provided', { status: 400 });
return createResponse('Error: No S3 channel provided', { status: 400 });
}
const { endpoint, accessKeyId, secretAccessKey, bucketName, region } = s3Channel;
@@ -361,7 +378,7 @@ async function uploadFileToS3(env, formdata, fullId, metadata, returnLink, origi
// 获取文件
const file = formdata.get("file");
if (!file) return new Response("Error: No file provided", { status: 400 });
if (!file) return createResponse("Error: No file provided", { status: 400 });
// 转换 Blob 为 Uint8Array
const arrayBuffer = await file.arrayBuffer();
@@ -399,7 +416,7 @@ async function uploadFileToS3(env, formdata, fullId, metadata, returnLink, origi
try {
await env.img_url.put(fullId, "", { metadata });
} catch {
return new Response("Error: Failed to write to KV database", { status: 500 });
return createResponse("Error: Failed to write to KV database", { status: 500 });
}
const moderateUrl = `https://${originUrl.hostname}/file/${fullId}`;
@@ -411,15 +428,17 @@ async function uploadFileToS3(env, formdata, fullId, metadata, returnLink, origi
try {
await env.img_url.put(fullId, "", { metadata });
} catch {
return new Response("Error: Failed to write to KV database", { status: 500 });
return createResponse("Error: Failed to write to KV database", { status: 500 });
}
return new Response(JSON.stringify([{ src: returnLink }]), {
return createResponse(JSON.stringify([{ src: returnLink }]), {
status: 200,
headers: { "Content-Type": "application/json" },
headers: {
"Content-Type": "application/json",
},
});
} catch (error) {
return new Response(`Error: Failed to upload to S3 - ${error.message}`, { status: 500 });
return createResponse(`Error: Failed to upload to S3 - ${error.message}`, { status: 500 });
}
}
@@ -430,7 +449,7 @@ async function uploadFileToTelegram(env, formdata, fullId, metadata, fileExt, fi
const tgChannels = tgSettings.channels;
const tgChannel = tgSettings.loadBalance.enabled? tgChannels[Math.floor(Math.random() * tgChannels.length)] : tgChannels[0];
if (!tgChannel) {
return new Response('Error: No Telegram channel provided', { status: 400 });
return createResponse('Error: No Telegram channel provided', { status: 400 });
}
const tgBotToken = tgChannel.botToken;
@@ -492,7 +511,7 @@ async function uploadFileToTelegram(env, formdata, fullId, metadata, fileExt, fi
// 向目标 URL 发送请求
let res = new Response('upload error, check your environment params about telegram channel!', { status: 400 });
let res = createResponse('upload error, check your environment params about telegram channel!', { status: 400 });
try {
const response = await fetch(targetUrl.href, {
method: clonedRequest.method,
@@ -510,11 +529,13 @@ async function uploadFileToTelegram(env, formdata, fullId, metadata, fileExt, fi
// 若上传成功,将响应返回给客户端
if (response.ok) {
res = new Response(
res = createResponse(
JSON.stringify([{ 'src': `${returnLink}` }]),
{
status: 200,
headers: { 'Content-Type': 'application/json' }
headers: {
'Content-Type': 'application/json',
}
}
);
}
@@ -536,10 +557,10 @@ async function uploadFileToTelegram(env, formdata, fullId, metadata, fileExt, fi
metadata: metadata,
});
} catch (error) {
res = new Response('Error: Failed to write to KV database', { status: 500 });
res = createResponse('Error: Failed to write to KV database', { status: 500 });
}
} catch (error) {
res = new Response('upload error, check your environment params about telegram channel!', { status: 400 });
res = createResponse('upload error, check your environment params about telegram channel!', { status: 400 });
} finally {
return res;
}
@@ -554,7 +575,7 @@ async function uploadFileToExternal(env, formdata, fullId, metadata, returnLink,
// 从 formdata 中获取外链
const extUrl = formdata.get('url');
if (extUrl === null || extUrl === undefined) {
return new Response('Error: No url provided', { status: 400 });
return createResponse('Error: No url provided', { status: 400 });
}
metadata.ExternalLink = extUrl;
// 写入KV数据库
@@ -563,15 +584,17 @@ async function uploadFileToExternal(env, formdata, fullId, metadata, returnLink,
metadata: metadata,
});
} catch (error) {
return new Response('Error: Failed to write to KV database', { status: 500 });
return createResponse('Error: Failed to write to KV database', { status: 500 });
}
// 返回结果
return new Response(
return createResponse(
JSON.stringify([{ 'src': `${returnLink}` }]),
{
status: 200,
headers: { 'Content-Type': 'application/json' }
headers: {
'Content-Type': 'application/json',
}
}
);
}