mirror of
https://github.com/ZSCGR/CloudFlare-ImgBed.git
synced 2026-08-13 04:03:42 +08:00
@@ -13,17 +13,20 @@ export async function onRequest(context) {
|
||||
|
||||
// 组装 CDN URL
|
||||
const url = new URL(request.url);
|
||||
const cdnUrl = `https://${url.hostname}/file/${params.id}`;
|
||||
|
||||
// 解码params.id
|
||||
params.id = decodeURIComponent(params.id);
|
||||
if (params.path) {
|
||||
params.path = String(params.path).split(',').join('/');
|
||||
}
|
||||
const cdnUrl = `https://${url.hostname}/file/${params.path}`;
|
||||
// 解码params.path
|
||||
params.path = decodeURIComponent(params.path);
|
||||
|
||||
//read the metadata
|
||||
const value = await env.img_url.getWithMetadata(params.id);
|
||||
const value = await env.img_url.getWithMetadata(params.path);
|
||||
|
||||
//change the metadata
|
||||
value.metadata.ListType = "Block"
|
||||
await env.img_url.put(params.id,"",{metadata: value.metadata});
|
||||
await env.img_url.put(params.path,"",{metadata: value.metadata});
|
||||
const info = JSON.stringify(value.metadata);
|
||||
|
||||
// 清除CDN缓存
|
||||
@@ -13,18 +13,18 @@ export async function onRequest(context) {
|
||||
} = context;
|
||||
// 组装 CDN URL
|
||||
const url = new URL(request.url);
|
||||
const cdnUrl = `https://${url.hostname}/file/${params.id}`;
|
||||
const cdnUrl = `https://${url.hostname}/file/${params.path}`;
|
||||
|
||||
// 解码params.id
|
||||
params.id = decodeURIComponent(params.id);
|
||||
// 解码params.path
|
||||
params.path = decodeURIComponent(params.path);
|
||||
|
||||
try {
|
||||
// 读取图片信息
|
||||
const img = await env.img_url.getWithMetadata(params.id);
|
||||
const img = await env.img_url.getWithMetadata(params.path);
|
||||
|
||||
// 如果是R2渠道的图片,删除R2中对应的图片
|
||||
if (img.metadata?.Channel === 'CloudflareR2') {
|
||||
await env.img_r2.delete(params.id);
|
||||
await env.img_r2.delete(params.path);
|
||||
}
|
||||
|
||||
// S3 渠道的图片,删除S3中对应的图片
|
||||
@@ -55,8 +55,8 @@ export async function onRequest(context) {
|
||||
}
|
||||
|
||||
// 删除KV中的图片信息
|
||||
await env.img_url.delete(params.id);
|
||||
const info = JSON.stringify(params.id);
|
||||
await env.img_url.delete(params.path);
|
||||
const info = JSON.stringify(params.path);
|
||||
|
||||
// 清除CDN缓存
|
||||
await purgeCFCache(env, cdnUrl);
|
||||
@@ -12,17 +12,20 @@ export async function onRequest(context) {
|
||||
} = context;
|
||||
// 组装 CDN URL
|
||||
const url = new URL(request.url);
|
||||
const cdnUrl = `https://${url.hostname}/file/${params.id}`;
|
||||
|
||||
// 解码params.id
|
||||
params.id = decodeURIComponent(params.id);
|
||||
if (params.path) {
|
||||
params.path = String(params.path).split(',').join('/');
|
||||
}
|
||||
const cdnUrl = `https://${url.hostname}/file/${params.path}`;
|
||||
// 解码params.path
|
||||
params.path = decodeURIComponent(params.path);
|
||||
|
||||
//read the metadata
|
||||
const value = await env.img_url.getWithMetadata(params.id);
|
||||
const value = await env.img_url.getWithMetadata(params.path);
|
||||
|
||||
//change the metadata
|
||||
value.metadata.ListType = "White"
|
||||
await env.img_url.put(params.id,"",{metadata: value.metadata});
|
||||
await env.img_url.put(params.path,"",{metadata: value.metadata});
|
||||
const info = JSON.stringify(value.metadata);
|
||||
|
||||
// 清除CDN缓存
|
||||
@@ -15,10 +15,13 @@ export async function onRequest(context) { // Contents of context object
|
||||
next, // used for middleware or to fetch assets
|
||||
data, // arbitrary space for passing data between middlewares
|
||||
} = context;
|
||||
|
||||
let fileId;
|
||||
try {
|
||||
// 解码params.id
|
||||
params.id = decodeURIComponent(params.id);
|
||||
// 解码params.path
|
||||
params.path = decodeURIComponent(params.path);
|
||||
// 从path中提取文件ID
|
||||
fileId = params.path.split(',').join('/');
|
||||
|
||||
} catch (e) {
|
||||
return new Response('Error: Decode Image ID Failed', { status: 400 });
|
||||
}
|
||||
@@ -29,13 +32,13 @@ export async function onRequest(context) { // Contents of context object
|
||||
whiteListMode = securityConfig.access.whiteListMode;
|
||||
|
||||
const url = new URL(request.url);
|
||||
let Referer = request.headers.get('Referer');
|
||||
let Referer = request.headers.get('Referer')
|
||||
if (Referer) {
|
||||
try {
|
||||
let refererUrl = new URL(Referer);
|
||||
if (allowedDomains && allowedDomains.trim() !== '') {
|
||||
let allowedDomainsList = allowedDomains.split(',');
|
||||
let isAllowed = allowedDomainsList.some(domain => {
|
||||
const domains = allowedDomains.split(',');
|
||||
let isAllowed = domains.some(domain => {
|
||||
let domainPattern = new RegExp(`(^|\\.)${domain.replace('.', '\\.')}$`); // Escape dot in domain
|
||||
return domainPattern.test(refererUrl.hostname);
|
||||
});
|
||||
@@ -51,10 +54,16 @@ export async function onRequest(context) { // Contents of context object
|
||||
if (typeof env.img_url == "undefined" || env.img_url == null || env.img_url == "") {
|
||||
return new Response('Error: Please configure KV database', { status: 500 });
|
||||
}
|
||||
const imgRecord = await env.img_url.getWithMetadata(params.id);
|
||||
// 如果meatdata不存在,只可能是之前未设置KV,且存储在Telegraph上的图片,那么在后面获取时会返回404错误,此处不用处理
|
||||
const imgRecord = await env.img_url.getWithMetadata(fileId);
|
||||
if (!imgRecord) {
|
||||
return new Response('Error: Image Not Found', { status: 404 });
|
||||
}
|
||||
// 如果metadata不存在,只可能是之前未设置KV,且存储在Telegraph上的图片
|
||||
if (!imgRecord.metadata) {
|
||||
imgRecord.metadata = {};
|
||||
}
|
||||
|
||||
const fileName = imgRecord.metadata?.FileName || params.id;
|
||||
const fileName = imgRecord.metadata?.FileName || fileId;
|
||||
const encodedFileName = encodeURIComponent(fileName);
|
||||
const fileType = imgRecord.metadata?.FileType || null;
|
||||
|
||||
@@ -64,8 +73,6 @@ export async function onRequest(context) { // Contents of context object
|
||||
return accessRes; // 如果不可访问,直接返回
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Cloudflare R2渠道
|
||||
if (imgRecord.metadata?.Channel === 'CloudflareR2') {
|
||||
// 检查是否配置了R2
|
||||
@@ -74,7 +81,7 @@ export async function onRequest(context) { // Contents of context object
|
||||
}
|
||||
|
||||
const R2DataBase = env.img_r2;
|
||||
const object = await R2DataBase.get(params.id);
|
||||
const object = await R2DataBase.get(fileId);
|
||||
|
||||
if (object === null) {
|
||||
return new Response('Error: Failed to fetch image', { status: 500 });
|
||||
@@ -103,7 +110,6 @@ export async function onRequest(context) { // Contents of context object
|
||||
return newRes;
|
||||
}
|
||||
|
||||
|
||||
// S3渠道
|
||||
if (imgRecord.metadata?.Channel === "S3") {
|
||||
const s3Client = new S3Client({
|
||||
@@ -151,15 +157,6 @@ export async function onRequest(context) { // Contents of context object
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 外链渠道
|
||||
if (imgRecord.metadata?.Channel === 'External') {
|
||||
// 直接重定向到外链
|
||||
return Response.redirect(imgRecord.metadata?.ExternalLink, 302);
|
||||
}
|
||||
|
||||
|
||||
// Telegram及Telegraph渠道
|
||||
let TgFileID = ''; // Tg的file_id
|
||||
if (imgRecord.metadata?.Channel === 'Telegram') {
|
||||
@@ -174,7 +171,6 @@ export async function onRequest(context) { // Contents of context object
|
||||
} else {
|
||||
// 旧版telegraph
|
||||
}
|
||||
|
||||
// 构建目标 URL
|
||||
if (isTgChannel(imgRecord)) {
|
||||
// 获取TG图片真实地址
|
||||
@@ -187,14 +183,12 @@ export async function onRequest(context) { // Contents of context object
|
||||
} else {
|
||||
targetUrl = 'https://telegra.ph/' + url.pathname + url.search;
|
||||
}
|
||||
|
||||
const response = await getFileContent(request);
|
||||
if (response === null) {
|
||||
return new Response('Error: Failed to fetch image', { status: 500 });
|
||||
} else if (response.status === 404) {
|
||||
return await return404(url);
|
||||
}
|
||||
|
||||
try {
|
||||
const headers = new Headers(response.headers);
|
||||
headers.set('Content-Disposition', `inline; filename="${encodedFileName}"; filename*=UTF-8''${encodedFileName}`);
|
||||
@@ -208,13 +202,11 @@ export async function onRequest(context) { // Contents of context object
|
||||
} else {
|
||||
headers.set('Cache-Control', 'public, max-age=604800');
|
||||
}
|
||||
|
||||
const newRes = new Response(response.body, {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
headers,
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
return newRes;
|
||||
}
|
||||
+16
-46
@@ -97,6 +97,15 @@ export async function onRequestPost(context) { // Contents of context object
|
||||
|
||||
// 获得上传渠道
|
||||
const urlParamUploadChannel = url.searchParams.get('uploadChannel');
|
||||
// 获取上传文件夹路径
|
||||
const uploadFolder = url.searchParams.get('uploadFolder') || '';
|
||||
// 处理文件夹路径格式,确保没有开头的/
|
||||
const normalizedFolder = uploadFolder
|
||||
? uploadFolder.replace(/^\/+/, '') // 移除开头的/
|
||||
.replace(/\/{2,}/g, '/') // 替换多个连续的/为单个/
|
||||
.replace(/\/$/, '') // 移除末尾的/
|
||||
: '';
|
||||
|
||||
let uploadChannel = 'TelegramNew';
|
||||
switch (urlParamUploadChannel) {
|
||||
case 'telegram':
|
||||
@@ -108,9 +117,6 @@ export async function onRequestPost(context) { // Contents of context object
|
||||
case 's3':
|
||||
uploadChannel = 'S3';
|
||||
break;
|
||||
case 'external':
|
||||
uploadChannel = 'External';
|
||||
break;
|
||||
default:
|
||||
uploadChannel = 'TelegramNew';
|
||||
break;
|
||||
@@ -141,6 +147,7 @@ export async function onRequestPost(context) { // Contents of context object
|
||||
ListType: "None",
|
||||
TimeStamp: time,
|
||||
Label: "None",
|
||||
Folder: normalizedFolder || 'root',
|
||||
}
|
||||
|
||||
|
||||
@@ -164,24 +171,21 @@ export async function onRequestPost(context) { // Contents of context object
|
||||
const unique_index = time + Math.floor(Math.random() * 10000);
|
||||
let fullId = '';
|
||||
if (nameType === 'index') {
|
||||
// 仅前缀
|
||||
fullId = unique_index + '.' + fileExt;
|
||||
// 只在 normalizedFolder 非空时添加路径
|
||||
fullId = normalizedFolder ? `${normalizedFolder}/${unique_index}.${fileExt}` : `${unique_index}.${fileExt}`;
|
||||
} else if (nameType === 'origin') {
|
||||
// 仅文件名
|
||||
fullId = fileName? fileName : unique_index + '.' + fileExt;
|
||||
fullId = normalizedFolder ? `${normalizedFolder}/${fileName}` : fileName;
|
||||
} else if (nameType === 'short') {
|
||||
// 短链接,8位大小写字母+数字的随机字符
|
||||
while (true) {
|
||||
const shortId = generateShortId(8);
|
||||
const testFullId = shortId + '.' + fileExt;
|
||||
const testFullId = normalizedFolder ? `${normalizedFolder}/${shortId}.${fileExt}` : `${shortId}.${fileExt}`;
|
||||
if (await env.img_url.get(testFullId) === null) {
|
||||
fullId = shortId + '.' + fileExt;
|
||||
fullId = testFullId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 默认方式:前缀+文件名
|
||||
fullId = fileName? unique_index + '_' + fileName : unique_index + '.' + fileExt;
|
||||
fullId = normalizedFolder ? `${normalizedFolder}/${unique_index}_${fileName}` : `${unique_index}_${fileName}`;
|
||||
}
|
||||
|
||||
// 获得返回链接格式, default为返回/file/id, full为返回完整链接
|
||||
@@ -220,10 +224,6 @@ export async function onRequestPost(context) { // Contents of context object
|
||||
} else {
|
||||
err = await res.text();
|
||||
}
|
||||
} else if (uploadChannel === 'External') {
|
||||
// -------------外链渠道---------------
|
||||
const res = await uploadFileToExternal(env, formdata, fullId, metadata, returnLink, url);
|
||||
return res;
|
||||
} else {
|
||||
// ----------------Telegram New 渠道-------------------
|
||||
const res = await uploadFileToTelegram(env, formdata, fullId, metadata, fileExt, fileName, fileType, url, clonedRequest, returnLink);
|
||||
@@ -530,36 +530,6 @@ async function uploadFileToTelegram(env, formdata, fullId, metadata, fileExt, fi
|
||||
}
|
||||
|
||||
|
||||
// 外链渠道
|
||||
async function uploadFileToExternal(env, formdata, fullId, metadata, returnLink, originUrl) {
|
||||
// 直接将外链写入metadata
|
||||
metadata.Channel = "External";
|
||||
metadata.ChannelName = "External";
|
||||
// 从 formdata 中获取外链
|
||||
const extUrl = formdata.get('url');
|
||||
if (extUrl === null || extUrl === undefined) {
|
||||
return new Response('Error: No url provided', { status: 400 });
|
||||
}
|
||||
metadata.ExternalLink = extUrl;
|
||||
// 写入KV数据库
|
||||
try {
|
||||
await env.img_url.put(fullId, "", {
|
||||
metadata: metadata,
|
||||
});
|
||||
} catch (error) {
|
||||
return new Response('Error: Failed to write to KV database', { status: 500 });
|
||||
}
|
||||
|
||||
// 返回结果
|
||||
return new Response(
|
||||
JSON.stringify([{ 'src': `${returnLink}` }]),
|
||||
{
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// 图像审查
|
||||
async function moderateContent(env, url, metadata) {
|
||||
const apikey = moderateContentApiKey;
|
||||
|
||||
Reference in New Issue
Block a user