[{"data":1,"prerenderedAt":3059},["ShallowReactive",2],{"article-\u002Fblog\u002F10-技术专栏\u002F40-WebsiteBuilding\u002F07-腾讯云-EdgeOne-边缘函数实现七牛-S3-随机图床-API":3,"article-around-\u002Fblog\u002F10-技术专栏\u002F40-WebsiteBuilding\u002F07-腾讯云-EdgeOne-边缘函数实现七牛-S3-随机图床-API":2841},{"id":4,"title":5,"author":6,"body":7,"category":2827,"cover":2828,"date":2829,"description":5,"draft":2830,"extension":2831,"image":2832,"license":2828,"meta":2833,"minutes":260,"navigation":612,"path":2834,"pinned":2830,"seo":2835,"stem":2836,"tags":2837,"__hash__":2840},"blog\u002Fblog\u002F10-技术专栏\u002F40-WebsiteBuilding\u002F07-腾讯云 EdgeOne 边缘函数实现七牛&S3 随机图床 API.md","腾讯云 EdgeOne 边缘函数实现七牛云 & S3 存储随机图床 API","张萌萌",{"type":8,"value":9,"toc":2794},"minimark",[10,15,24,45,56,59,63,68,96,100,202,206,212,214,218,222,318,346,350,378,380,384,439,452,454,458,462,519,523,547,551,580,2497,2501,2532,2534,2538,2542,2576,2580,2601,2605,2623,2627,2643,2645,2649,2653,2684,2688,2733,2735,2739,2743,2760,2764,2787,2790],[11,12,14],"h2",{"id":13},"_1-序言-️","1 序言 🖼️",[16,17,18,19,23],"p",{},"个人静态博客存在壁纸分层展示需求，",[20,21,22],"strong",{},"PC"," 端宽屏壁纸、移动端竖屏壁纸需要两套独立图库，前端直连对象存储存在多重业务痛点：",[25,26,27,31,38],"ul",{},[28,29,30],"li",{},"统一图库混存图片，随机接口返回图片比例与设备不匹配，页面展示效果差；",[28,32,33,34,37],{},"前端直接请求存储域名触发 ",[20,35,36],{},"CORS"," 跨域拦截，同时持续消耗源站下行流量，抬高存储计费；",[28,39,40,41,44],{},"对象存储真实域名、",[20,42,43],{},"AK \u002F SK"," 鉴权密钥暴露客户端，存在文件盗刷、资源泄露风险。",[16,46,47,48,51,52,55],{},"依托腾讯云 ",[20,49,50],{},"EdgeOne"," 边缘函数搭建转发中间层，边缘接入点直出图片二进制流，天然实现 ",[20,53,54],{},"PC \u002F 移动端"," 图库物理隔离、边缘缓存降费、统一跨域处理、全链路异常兜底，无需后端服务即可完成可落地随机图床 API。",[57,58],"hr",{},[11,60,62],{"id":61},"_2-业务需求与方案选型对比","2 业务需求与方案选型对比",[64,65,67],"h3",{"id":66},"_21-项目约束","2.1 项目约束",[25,69,70,76,82,89],{},[28,71,72,73,75],{},"资源分离：",[20,74,22],{},"、移动端图片池使用独立存储目录，通过请求路由自动绑定对应图库，前端无需额外传参区分设备；",[28,77,78,79,81],{},"跨域解决：前端页面直接调用接口，无需在存储侧配置 ",[20,80,36],{},"，兼容 fetch、axios 等主流请求库；",[28,83,84,85,88],{},"缓存降费：边缘接入点缓存图片二进制资源，减少七牛云 \u002F ",[20,86,87],{},"S3"," 源站回源请求与下行流量；",[28,90,91,92,95],{},"异常容错：目录无图片、存储鉴权失败、网络超时、资源 ",[20,93,94],{},"404"," 场景自动返回兜底占位图，避免页面空白报错。",[64,97,99],{"id":98},"_22-两种实现方案三线对比","2.2 两种实现方案三线对比",[101,102,103,119],"table",{},[104,105,106],"thead",{},[107,108,109,113,116],"tr",{},[110,111,112],"th",{},"对比维度",[110,114,115],{},"302 重定向方案",[110,117,118],{},"EdgeOne 边缘接入点直出图片流",[120,121,122,134,145,163,180,191],"tbody",{},[107,123,124,128,131],{},[125,126,127],"td",{},"流量链路",[125,129,130],{},"用户 → 边缘接入点 → 302 跳转 → 对象存储源站",[125,132,133],{},"用户 → 就近边缘接入点，边缘回源存储拉取图片，二进制流直接返回客户端",[107,135,136,139,142],{},[125,137,138],{},"缓存能力",[125,140,141],{},"仅缓存 302 响应头，图片本体无法缓存",[125,143,144],{},"完整缓存图片二进制数据，同区域重复访问无源站流量",[107,146,147,150,160],{},[125,148,149],{},"密钥安全",[125,151,152,153,156,157,159],{},"前端可捕获存储 ",[20,154,155],{},"CDN"," 域名，",[20,158,43],{}," 存在泄露盗刷风险",[125,161,162],{},"密钥存放边缘环境变量，前端无法感知存储地址与鉴权信息",[107,164,165,168,174],{},[125,166,167],{},"跨域运维",[125,169,170,171,173],{},"每个存储桶单独配置 ",[20,172,36],{},"，多存储场景运维繁琐",[125,175,176,177,179],{},"边缘统一输出跨域响应头，一套规则适配全部 ",[20,178,87],{}," 兼容存储",[107,181,182,185,188],{},[125,183,184],{},"异常降级",[125,186,187],{},"资源失效直接返回 404，无兜底展示逻辑",[125,189,190],{},"边缘捕获全链路异常，自动切换预设兜底图片返回",[107,192,193,196,199],{},[125,194,195],{},"长期成本",[125,197,198],{},"源站下行流量持续消耗，存储计费偏高",[125,200,201],{},"边缘缓存命中占比提升后，源站流量成本大幅下降",[64,203,205],{"id":204},"_23-方案选型结论","2.3 方案选型结论",[16,207,208,209,211],{},"优先选用 ",[20,210,118],{}," 架构。\n该方案在存储安全、流量成本、运维复杂度、异常容错四大维度全面优于 302 重定向，适配静态博客、轻量化站点高频调用随机图床接口的长期运营场景，零后端架构大幅降低服务器运维成本。",[57,213],{},[11,215,217],{"id":216},"_3-整体架构与运行链路","3 整体架构与运行链路",[64,219,221],{"id":220},"_31-完整请求链路流程图文字说明","3.1 完整请求链路流程图文字说明",[223,224,229],"pre",{"className":225,"code":226,"language":227,"meta":228,"style":228},"language-mermaid shiki shiki-themes github-light github-dark","flowchart LR\nA[用户浏览器] --> B[EdgeOne全球边缘接入点]\nB --> C{路由匹配判断}\nC -->|\u002Fapi 路由| D[读取PC图库目录 blog\u002Fbg\u002F]\nC -->|\u002Fm-api 路由| E[读取移动端图库目录 blog\u002Fbg-m\u002F]\nD & E --> F[携带鉴权签名请求存储获取图片列表]\nF --> G[随机选取单张图片资源]\nG --> H[边缘回源拉取图片二进制流]\nH --> I[追加跨域、缓存响应头]\nI --> B\nB --> A\nJ[边缘本地缓存图片] --> B\nF -->|请求异常\u002F目录无图| K[加载兜底默认图片]\nK --> I\n","mermaid","",[230,231,232,240,246,252,258,264,270,276,282,288,294,300,306,312],"code",{"__ignoreMap":228},[233,234,237],"span",{"class":235,"line":236},"line",1,[233,238,239],{},"flowchart LR\n",[233,241,243],{"class":235,"line":242},2,[233,244,245],{},"A[用户浏览器] --> B[EdgeOne全球边缘接入点]\n",[233,247,249],{"class":235,"line":248},3,[233,250,251],{},"B --> C{路由匹配判断}\n",[233,253,255],{"class":235,"line":254},4,[233,256,257],{},"C -->|\u002Fapi 路由| D[读取PC图库目录 blog\u002Fbg\u002F]\n",[233,259,261],{"class":235,"line":260},5,[233,262,263],{},"C -->|\u002Fm-api 路由| E[读取移动端图库目录 blog\u002Fbg-m\u002F]\n",[233,265,267],{"class":235,"line":266},6,[233,268,269],{},"D & E --> F[携带鉴权签名请求存储获取图片列表]\n",[233,271,273],{"class":235,"line":272},7,[233,274,275],{},"F --> G[随机选取单张图片资源]\n",[233,277,279],{"class":235,"line":278},8,[233,280,281],{},"G --> H[边缘回源拉取图片二进制流]\n",[233,283,285],{"class":235,"line":284},9,[233,286,287],{},"H --> I[追加跨域、缓存响应头]\n",[233,289,291],{"class":235,"line":290},10,[233,292,293],{},"I --> B\n",[233,295,297],{"class":235,"line":296},11,[233,298,299],{},"B --> A\n",[233,301,303],{"class":235,"line":302},12,[233,304,305],{},"J[边缘本地缓存图片] --> B\n",[233,307,309],{"class":235,"line":308},13,[233,310,311],{},"F -->|请求异常\u002F目录无图| K[加载兜底默认图片]\n",[233,313,315],{"class":235,"line":314},14,[233,316,317],{},"K --> I\n",[25,319,320,334,337,340,343],{},[28,321,322,323,326,327,330,331,333],{},"用户发起 ",[230,324,325],{},"\u002Fapi"," 或 ",[230,328,329],{},"\u002Fm-api"," 接口请求，流量调度至就近 ",[20,332,50],{}," 边缘接入点；",[28,335,336],{},"边缘函数匹配请求路由绑定对应资源目录，携带鉴权签名调用存储文件列表接口；",[28,338,339],{},"过滤图片格式后随机选取资源，边缘接入点回源拉取图片二进制；",[28,341,342],{},"统一拼接跨域、长缓存响应头，图片流返回客户端并在边缘本地缓存；",[28,344,345],{},"链路任意环节触发异常时，自动加载兜底图片返回，保障页面正常渲染。",[64,347,349],{"id":348},"_32-资源分层规则","3.2 资源分层规则",[25,351,352,365,375],{},[28,353,354,356,357,360,361,364],{},[20,355,22],{}," 端图库目录：",[230,358,359],{},"blog\u002Fbg\u002F","，存放 ",[20,362,363],{},"16:9 \u002F 21:9"," 宽屏高清壁纸，适配桌面端展示；",[28,366,367,368,360,371,374],{},"移动端图库目录：",[230,369,370],{},"blog\u002Fbg-m\u002F",[20,372,373],{},"9:16"," 竖屏壁纸，适配手机、平板竖屏场景；",[28,376,377],{},"两套目录物理隔离，接口路由自动绑定对应目录，前端无需传递设备标识参数。",[57,379],{},[11,381,383],{"id":382},"_4-获取七牛云密钥兼容标准-s3-存储","4 获取七牛云密钥（兼容标准 S3 存储）",[25,385,386,419],{},[28,387,388,389],{},"七牛云密钥获取流程\n",[25,390,391,402,413],{},[28,392,393,394,401],{},"登录",[395,396,400],"a",{"href":397,"rel":398},"https:\u002F\u002Fportal.qiniu.com\u002Fdeveloper\u002Fuser\u002Fkey",[399],"nofollow","七牛云控制台","，进入个人中心 - 密钥管理页面；",[28,403,404,405,408,409,412],{},"复制 ",[20,406,407],{},"AccessKey(AK)","、",[20,410,411],{},"SecretKey(SK)"," 两组鉴权密钥；",[28,414,415,416,418],{},"记录存储空间名称、",[20,417,155],{}," 访问域名、线上兜底图片完整地址。",[28,420,421,423,424,427,428,431,432,434,435],{},[20,422,87],{}," 通用存储适配说明\n阿里云 ",[20,425,426],{},"OSS","、腾讯云 ",[20,429,430],{},"COS","、MinIO 等标准 ",[20,433,87],{}," 对象存储仅需重写签名生成函数、替换存储列表请求域名，边缘代理整体业务逻辑无需改动。\n",[436,437],"img",{"alt":228,"src":438},"https:\u002F\u002Fimg.nw177.cn\u002Fblog\u002F2026\u002F07\u002F13\u002F1783953543543.avif",[440,441,442],"blockquote",{},[16,443,444,445,448,449,451],{},"⚠️ 关键避坑警告：生产环境严禁将 ",[20,446,447],{},"AK、SK"," 密钥硬编码写入边缘函数源码，必须通过 ",[20,450,50],{}," 环境变量配置密钥，防止源码泄露导致存储文件被盗刷、产生高额流量账单。",[57,453],{},[11,455,457],{"id":456},"_5-腾讯-edgeone-边缘函数","5 腾讯 EdgeOne 边缘函数",[64,459,461],{"id":460},"_51-添加触发边缘函数的域名","5.1 添加触发边缘函数的域名",[25,463,464,478,484,490,495,498,513],{},[28,465,466,467,473,474,477],{},"进入 ",[20,468,469],{},[395,470,50],{"href":471,"rel":472},"https:\u002F\u002Fconsole.cloud.tencent.com\u002Fedgeone\u002Fzones",[399]," 控制台站点管理，接入业务域名并完成 ",[20,475,476],{},"DNS"," 解析生效；",[28,479,480,481],{},"域名配置，加速域名：",[230,482,483],{},"api.img.你的备案域名.com",[28,485,486,487],{},"回源配置，IP 域名：",[20,488,489],{},"119.29.29.29",[28,491,492,493],{},"回源配置，回源 HOST 头：",[230,494,483],{},[28,496,497],{},"不使用模板，下一步解析 DNS 就可以",[28,499,500,501,504,505,508,509,512],{},"配置 ",[20,502,503],{},"SSL"," 证书，开启全站 ",[20,506,507],{},"HTTPS"," 强制跳转，关闭 ",[20,510,511],{},"HTTP"," 明文访问；",[28,514,515,516],{},"开启域名边缘函数执行权限，限制流量直接回源源站。\n",[436,517],{"alt":228,"src":518},"https:\u002F\u002Fimg.nw177.cn\u002Fblog\u002F2026\u002F07\u002F13\u002F1783954579728.avif",[64,520,522],{"id":521},"_52-创建边缘函数","5.2 创建边缘函数",[25,524,525,535,538,541],{},[28,526,527,528,531,532],{},"侧边栏选择边缘函数，新建函数，运行环境选择 ",[20,529,530],{},"创建 Hello World","；\n",[436,533],{"alt":228,"src":534},"https:\u002F\u002Fimg.nw177.cn\u002Fblog\u002F2026\u002F07\u002F13\u002F1783956091651.avif",[28,536,537],{},"函数名称：api-img",[28,539,540],{},"描述：随机图床 API",[28,542,543,544],{},"函数代码：全部删除，填写函数代码，先空着创建部署也可以。\n",[436,545],{"alt":228,"src":546},"https:\u002F\u002Fimg.nw177.cn\u002Fblog\u002F2026\u002F07\u002F13\u002F1783956377110.avif",[64,548,550],{"id":549},"_53-编辑函数代码核心","5.3 编辑函数代码（核心）",[25,552,553,556,559,562,568,571,574],{},[28,554,555],{},"完整边缘函数源码",[28,557,558],{},"AK 密钥、SK 密钥",[28,560,561],{},"BUCKET 存储桶名称，例如 sinc-img",[28,563,564,565],{},"DOMAIN，最好填写套一层 CDN 的，EO的域名",[230,566,567],{},"img.你的备案域名.com",[28,569,570],{},"PC_PREFIX 电脑壁纸存储路径，例如 “blog\u002Fbg\u002F\"",[28,572,573],{},"MOBILE_PREFIX 手机端壁纸存储路径，例如 \"blog\u002Fbg-m\u002F\"",[28,575,576,577],{},"所以，你上传电脑壁纸和手机壁纸，就分别传这俩路径就可以\n",[436,578],{"alt":228,"src":579},"https:\u002F\u002Fimg.nw177.cn\u002Fblog\u002F2026\u002F07\u002F13\u002F1783957368843.avif",[223,581,585],{"className":582,"code":583,"language":584,"meta":228,"style":228},"language-javascript shiki shiki-themes github-light github-dark","\u002F**\n * 随机图 API - 腾讯云 EdgeOne 大满贯版\n * 特性：直连七牛云目录、极速内存缓存、边缘代理(零跨域、非302)\n *\u002F\n\n\u002F\u002F ==========================================\n\u002F\u002F 1. 核心配置区\n\u002F\u002F ==========================================\nconst CONFIG = {\n  AK: \"AK密钥\", \n  SK: \"SK密钥\",\n  BUCKET: \"七牛云存储空间名称\", \n  DOMAIN: \"最好填写套一层CDN的，EO的域名\", \u002F\u002F 你的图床 CDN 域名\n  \n  PC_PREFIX: \"blog\u002Fbg\u002F\",    \n  MOBILE_PREFIX: \"blog\u002Fbg-m\u002F\" \n};\n\n\u002F\u002F ==========================================\n\u002F\u002F 2. 全局内存缓存\n\u002F\u002F ==========================================\nlet pcImages = [];\nlet mobileImages = [];\nlet lastCheckTime = 0;\nconst CACHE_TTL = 3 * 60 * 1000; \u002F\u002F 3 分钟缓存\n\naddEventListener('fetch', event => {\n  event.respondWith(handleRequest(event.request))\n});\n\n\u002F\u002F ==========================================\n\u002F\u002F 3. 密码学：生成七牛云鉴权 Token\n\u002F\u002F ==========================================\nasync function generateQiniuToken(path) {\n  const signingStr = `${path}\\n`;\n  const encoder = new TextEncoder();\n  const key = await crypto.subtle.importKey(\n    'raw', encoder.encode(CONFIG.SK), \n    { name: 'HMAC', hash: 'SHA-1' }, false, ['sign']\n  );\n  const signature = await crypto.subtle.sign('HMAC', key, encoder.encode(signingStr));\n  const base64 = btoa(String.fromCharCode(...new Uint8Array(signature)));\n  const encodedSign = base64.replace(\u002F\\+\u002Fg, '-').replace(\u002F\\\u002F\u002Fg, '_');\n  return `QBox ${CONFIG.AK}:${encodedSign}`;\n}\n\n\u002F\u002F ==========================================\n\u002F\u002F 4. 抓取七牛云真实文件列表\n\u002F\u002F ==========================================\nasync function fetchImagesFromQiniu(prefix) {\n  try {\n    const apiPath = `\u002Flist?bucket=${CONFIG.BUCKET}&prefix=${prefix}&limit=1000`;\n    const apiHost = 'rsf.qiniuapi.com'; \n    const token = await generateQiniuToken(apiPath);\n    \n    const response = await fetch(`https:\u002F\u002F${apiHost}${apiPath}`, {\n      headers: {\n        'Authorization': token,\n        'Content-Type': 'application\u002Fx-www-form-urlencoded'\n      }\n    });\n\n    if (!response.ok) return [];\n\n    const data = await response.json();\n    if (!data.items) return [];\n\n    return data.items\n      .filter(item => item.mimeType && item.mimeType.startsWith('image\u002F'))\n      .map(item => `${CONFIG.DOMAIN}\u002F${item.key}`);\n      \n  } catch (error) {\n    console.error(`拉取目录 ${prefix} 失败:`, error);\n    return [];\n  }\n}\n\n\u002F\u002F ==========================================\n\u002F\u002F 5. 代理获取图片并注入跨域头 (核心新增逻辑)\n\u002F\u002F ==========================================\nasync function proxyImage(imageUrl) {\n  try {\n    \u002F\u002F 边缘接入点出面去你的 CDN 拿图\n    const response = await fetch(imageUrl, {\n      headers: {\n        \"User-Agent\": \"Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64) EdgeOne-Proxy\"\n      }\n    });\n\n    if (response.ok) {\n      \u002F\u002F 拿到图片后，重写响应头，强行允许跨域\n      const newHeaders = new Headers(response.headers);\n      newHeaders.set(\"Access-Control-Allow-Origin\", \"*\");\n      newHeaders.set(\"Cache-Control\", \"no-cache\"); \u002F\u002F 告诉浏览器不要缓存当前API链接，以免下次拿不到新图\n\n      \u002F\u002F 返回 200 状态码和真实图片数据流\n      return new Response(response.body, {\n        status: 200,\n        headers: newHeaders\n      });\n    }\n    \n    \u002F\u002F 如果图片代理失败，降级回 302 重定向\n    return Response.redirect(imageUrl, 302);\n  } catch (e) {\n    \u002F\u002F 网络异常，降级回 302 重定向\n    return Response.redirect(imageUrl, 302);\n  }\n}\n\n\u002F\u002F ==========================================\n\u002F\u002F 6. 主路由逻辑\n\u002F\u002F ==========================================\nasync function handleRequest(request) {\n  const url = new URL(request.url);\n  const route = url.pathname;\n\n  \u002F\u002F 初始化或更新缓存\n  if (Date.now() - lastCheckTime > CACHE_TTL || pcImages.length === 0 || mobileImages.length === 0) {\n    try {\n      const [newPc, newMobile] = await Promise.all([\n        fetchImagesFromQiniu(CONFIG.PC_PREFIX),\n        fetchImagesFromQiniu(CONFIG.MOBILE_PREFIX)\n      ]);\n      \n      if (newPc.length > 0) pcImages = newPc;\n      if (newMobile.length > 0) mobileImages = newMobile;\n      lastCheckTime = Date.now();\n    } catch (e) {\n      console.error(\"更新列表失败，暂时使用旧缓存\");\n    }\n  }\n\n  \u002F\u002F --- 处理电脑壁纸 ---\n  if (route === '\u002Fapi') {\n    if (pcImages.length === 0) return new Response(\"初始化中...\", {status: 503});\n    const randomImg = pcImages[Math.floor(Math.random() * pcImages.length)];\n    \u002F\u002F 调用代理函数，直接返回图片流\n    return await proxyImage(randomImg);\n  }\n\n  \u002F\u002F --- 处理手机壁纸 ---\n  if (route === '\u002Fm-api') {\n    if (mobileImages.length === 0) return new Response(\"初始化中...\", {status: 503});\n    const randomImg = mobileImages[Math.floor(Math.random() * mobileImages.length)];\n    \u002F\u002F 调用代理函数，直接返回图片流\n    return await proxyImage(randomImg);\n  }\n\n  return new Response(\"API 正常运行。电脑壁纸请访问 \u002Fapi，手机壁纸请访问 \u002Fm-api\", { \n    status: 200, \n    headers: { \"Content-Type\": \"text\u002Fhtml;charset=UTF-8\" } \n  });\n}\n","javascript",[230,586,587,593,598,603,608,614,619,624,628,645,657,668,678,692,697,709,721,727,732,737,743,748,763,775,791,821,826,850,867,873,878,883,889,894,914,941,960,982,1008,1038,1044,1073,1103,1162,1189,1195,1200,1205,1211,1216,1233,1241,1272,1288,1305,1311,1345,1351,1360,1372,1378,1384,1389,1409,1414,1434,1450,1455,1464,1500,1537,1543,1555,1577,1584,1590,1595,1600,1605,1611,1616,1633,1640,1646,1662,1667,1678,1683,1688,1693,1701,1707,1726,1747,1770,1775,1781,1795,1806,1812,1818,1824,1829,1835,1854,1864,1870,1885,1890,1895,1900,1905,1911,1916,1933,1951,1964,1969,1975,2027,2035,2069,2087,2104,2110,2115,2139,2161,2176,2186,2201,2206,2211,2216,2222,2238,2274,2308,2314,2326,2331,2336,2342,2356,2388,2416,2421,2432,2437,2442,2459,2469,2486,2492],{"__ignoreMap":228},[233,588,589],{"class":235,"line":236},[233,590,592],{"class":591},"sJ8bj","\u002F**\n",[233,594,595],{"class":235,"line":242},[233,596,597],{"class":591}," * 随机图 API - 腾讯云 EdgeOne 大满贯版\n",[233,599,600],{"class":235,"line":248},[233,601,602],{"class":591}," * 特性：直连七牛云目录、极速内存缓存、边缘代理(零跨域、非302)\n",[233,604,605],{"class":235,"line":254},[233,606,607],{"class":591}," *\u002F\n",[233,609,610],{"class":235,"line":260},[233,611,613],{"emptyLinePlaceholder":612},true,"\n",[233,615,616],{"class":235,"line":266},[233,617,618],{"class":591},"\u002F\u002F ==========================================\n",[233,620,621],{"class":235,"line":272},[233,622,623],{"class":591},"\u002F\u002F 1. 核心配置区\n",[233,625,626],{"class":235,"line":278},[233,627,618],{"class":591},[233,629,630,634,638,641],{"class":235,"line":284},[233,631,633],{"class":632},"szBVR","const",[233,635,637],{"class":636},"sj4cs"," CONFIG",[233,639,640],{"class":632}," =",[233,642,644],{"class":643},"sVt8B"," {\n",[233,646,647,650,654],{"class":235,"line":290},[233,648,649],{"class":643},"  AK: ",[233,651,653],{"class":652},"sZZnC","\"AK密钥\"",[233,655,656],{"class":643},", \n",[233,658,659,662,665],{"class":235,"line":296},[233,660,661],{"class":643},"  SK: ",[233,663,664],{"class":652},"\"SK密钥\"",[233,666,667],{"class":643},",\n",[233,669,670,673,676],{"class":235,"line":302},[233,671,672],{"class":643},"  BUCKET: ",[233,674,675],{"class":652},"\"七牛云存储空间名称\"",[233,677,656],{"class":643},[233,679,680,683,686,689],{"class":235,"line":308},[233,681,682],{"class":643},"  DOMAIN: ",[233,684,685],{"class":652},"\"最好填写套一层CDN的，EO的域名\"",[233,687,688],{"class":643},", ",[233,690,691],{"class":591},"\u002F\u002F 你的图床 CDN 域名\n",[233,693,694],{"class":235,"line":314},[233,695,696],{"class":643},"  \n",[233,698,700,703,706],{"class":235,"line":699},15,[233,701,702],{"class":643},"  PC_PREFIX: ",[233,704,705],{"class":652},"\"blog\u002Fbg\u002F\"",[233,707,708],{"class":643},",    \n",[233,710,712,715,718],{"class":235,"line":711},16,[233,713,714],{"class":643},"  MOBILE_PREFIX: ",[233,716,717],{"class":652},"\"blog\u002Fbg-m\u002F\"",[233,719,720],{"class":643}," \n",[233,722,724],{"class":235,"line":723},17,[233,725,726],{"class":643},"};\n",[233,728,730],{"class":235,"line":729},18,[233,731,613],{"emptyLinePlaceholder":612},[233,733,735],{"class":235,"line":734},19,[233,736,618],{"class":591},[233,738,740],{"class":235,"line":739},20,[233,741,742],{"class":591},"\u002F\u002F 2. 全局内存缓存\n",[233,744,746],{"class":235,"line":745},21,[233,747,618],{"class":591},[233,749,751,754,757,760],{"class":235,"line":750},22,[233,752,753],{"class":632},"let",[233,755,756],{"class":643}," pcImages ",[233,758,759],{"class":632},"=",[233,761,762],{"class":643}," [];\n",[233,764,766,768,771,773],{"class":235,"line":765},23,[233,767,753],{"class":632},[233,769,770],{"class":643}," mobileImages ",[233,772,759],{"class":632},[233,774,762],{"class":643},[233,776,778,780,783,785,788],{"class":235,"line":777},24,[233,779,753],{"class":632},[233,781,782],{"class":643}," lastCheckTime ",[233,784,759],{"class":632},[233,786,787],{"class":636}," 0",[233,789,790],{"class":643},";\n",[233,792,794,796,799,801,804,807,810,812,815,818],{"class":235,"line":793},25,[233,795,633],{"class":632},[233,797,798],{"class":636}," CACHE_TTL",[233,800,640],{"class":632},[233,802,803],{"class":636}," 3",[233,805,806],{"class":632}," *",[233,808,809],{"class":636}," 60",[233,811,806],{"class":632},[233,813,814],{"class":636}," 1000",[233,816,817],{"class":643},"; ",[233,819,820],{"class":591},"\u002F\u002F 3 分钟缓存\n",[233,822,824],{"class":235,"line":823},26,[233,825,613],{"emptyLinePlaceholder":612},[233,827,829,833,836,839,841,845,848],{"class":235,"line":828},27,[233,830,832],{"class":831},"sScJk","addEventListener",[233,834,835],{"class":643},"(",[233,837,838],{"class":652},"'fetch'",[233,840,688],{"class":643},[233,842,844],{"class":843},"s4XuR","event",[233,846,847],{"class":632}," =>",[233,849,644],{"class":643},[233,851,853,856,859,861,864],{"class":235,"line":852},28,[233,854,855],{"class":643},"  event.",[233,857,858],{"class":831},"respondWith",[233,860,835],{"class":643},[233,862,863],{"class":831},"handleRequest",[233,865,866],{"class":643},"(event.request))\n",[233,868,870],{"class":235,"line":869},29,[233,871,872],{"class":643},"});\n",[233,874,876],{"class":235,"line":875},30,[233,877,613],{"emptyLinePlaceholder":612},[233,879,881],{"class":235,"line":880},31,[233,882,618],{"class":591},[233,884,886],{"class":235,"line":885},32,[233,887,888],{"class":591},"\u002F\u002F 3. 密码学：生成七牛云鉴权 Token\n",[233,890,892],{"class":235,"line":891},33,[233,893,618],{"class":591},[233,895,897,900,903,906,908,911],{"class":235,"line":896},34,[233,898,899],{"class":632},"async",[233,901,902],{"class":632}," function",[233,904,905],{"class":831}," generateQiniuToken",[233,907,835],{"class":643},[233,909,910],{"class":843},"path",[233,912,913],{"class":643},") {\n",[233,915,917,920,923,925,928,930,933,936,939],{"class":235,"line":916},35,[233,918,919],{"class":632},"  const",[233,921,922],{"class":636}," signingStr",[233,924,640],{"class":632},[233,926,927],{"class":652}," `${",[233,929,910],{"class":643},[233,931,932],{"class":652},"}",[233,934,935],{"class":636},"\\n",[233,937,938],{"class":652},"`",[233,940,790],{"class":643},[233,942,944,946,949,951,954,957],{"class":235,"line":943},36,[233,945,919],{"class":632},[233,947,948],{"class":636}," encoder",[233,950,640],{"class":632},[233,952,953],{"class":632}," new",[233,955,956],{"class":831}," TextEncoder",[233,958,959],{"class":643},"();\n",[233,961,963,965,968,970,973,976,979],{"class":235,"line":962},37,[233,964,919],{"class":632},[233,966,967],{"class":636}," key",[233,969,640],{"class":632},[233,971,972],{"class":632}," await",[233,974,975],{"class":643}," crypto.subtle.",[233,977,978],{"class":831},"importKey",[233,980,981],{"class":643},"(\n",[233,983,985,988,991,994,996,999,1002,1005],{"class":235,"line":984},38,[233,986,987],{"class":652},"    'raw'",[233,989,990],{"class":643},", encoder.",[233,992,993],{"class":831},"encode",[233,995,835],{"class":643},[233,997,998],{"class":636},"CONFIG",[233,1000,1001],{"class":643},".",[233,1003,1004],{"class":636},"SK",[233,1006,1007],{"class":643},"), \n",[233,1009,1011,1014,1017,1020,1023,1026,1029,1032,1035],{"class":235,"line":1010},39,[233,1012,1013],{"class":643},"    { name: ",[233,1015,1016],{"class":652},"'HMAC'",[233,1018,1019],{"class":643},", hash: ",[233,1021,1022],{"class":652},"'SHA-1'",[233,1024,1025],{"class":643}," }, ",[233,1027,1028],{"class":636},"false",[233,1030,1031],{"class":643},", [",[233,1033,1034],{"class":652},"'sign'",[233,1036,1037],{"class":643},"]\n",[233,1039,1041],{"class":235,"line":1040},40,[233,1042,1043],{"class":643},"  );\n",[233,1045,1047,1049,1052,1054,1056,1058,1061,1063,1065,1068,1070],{"class":235,"line":1046},41,[233,1048,919],{"class":632},[233,1050,1051],{"class":636}," signature",[233,1053,640],{"class":632},[233,1055,972],{"class":632},[233,1057,975],{"class":643},[233,1059,1060],{"class":831},"sign",[233,1062,835],{"class":643},[233,1064,1016],{"class":652},[233,1066,1067],{"class":643},", key, encoder.",[233,1069,993],{"class":831},[233,1071,1072],{"class":643},"(signingStr));\n",[233,1074,1076,1078,1081,1083,1086,1089,1092,1094,1097,1100],{"class":235,"line":1075},42,[233,1077,919],{"class":632},[233,1079,1080],{"class":636}," base64",[233,1082,640],{"class":632},[233,1084,1085],{"class":831}," btoa",[233,1087,1088],{"class":643},"(String.",[233,1090,1091],{"class":831},"fromCharCode",[233,1093,835],{"class":643},[233,1095,1096],{"class":632},"...new",[233,1098,1099],{"class":831}," Uint8Array",[233,1101,1102],{"class":643},"(signature)));\n",[233,1104,1106,1108,1111,1113,1116,1119,1121,1124,1128,1130,1133,1135,1138,1141,1143,1145,1147,1150,1152,1154,1156,1159],{"class":235,"line":1105},43,[233,1107,919],{"class":632},[233,1109,1110],{"class":636}," encodedSign",[233,1112,640],{"class":632},[233,1114,1115],{"class":643}," base64.",[233,1117,1118],{"class":831},"replace",[233,1120,835],{"class":643},[233,1122,1123],{"class":652},"\u002F",[233,1125,1127],{"class":1126},"snhLl","\\+",[233,1129,1123],{"class":652},[233,1131,1132],{"class":632},"g",[233,1134,688],{"class":643},[233,1136,1137],{"class":652},"'-'",[233,1139,1140],{"class":643},").",[233,1142,1118],{"class":831},[233,1144,835],{"class":643},[233,1146,1123],{"class":652},[233,1148,1149],{"class":1126},"\\\u002F",[233,1151,1123],{"class":652},[233,1153,1132],{"class":632},[233,1155,688],{"class":643},[233,1157,1158],{"class":652},"'_'",[233,1160,1161],{"class":643},");\n",[233,1163,1165,1168,1171,1173,1175,1178,1181,1184,1187],{"class":235,"line":1164},44,[233,1166,1167],{"class":632},"  return",[233,1169,1170],{"class":652}," `QBox ${",[233,1172,998],{"class":636},[233,1174,1001],{"class":652},[233,1176,1177],{"class":636},"AK",[233,1179,1180],{"class":652},"}:${",[233,1182,1183],{"class":643},"encodedSign",[233,1185,1186],{"class":652},"}`",[233,1188,790],{"class":643},[233,1190,1192],{"class":235,"line":1191},45,[233,1193,1194],{"class":643},"}\n",[233,1196,1198],{"class":235,"line":1197},46,[233,1199,613],{"emptyLinePlaceholder":612},[233,1201,1203],{"class":235,"line":1202},47,[233,1204,618],{"class":591},[233,1206,1208],{"class":235,"line":1207},48,[233,1209,1210],{"class":591},"\u002F\u002F 4. 抓取七牛云真实文件列表\n",[233,1212,1214],{"class":235,"line":1213},49,[233,1215,618],{"class":591},[233,1217,1219,1221,1223,1226,1228,1231],{"class":235,"line":1218},50,[233,1220,899],{"class":632},[233,1222,902],{"class":632},[233,1224,1225],{"class":831}," fetchImagesFromQiniu",[233,1227,835],{"class":643},[233,1229,1230],{"class":843},"prefix",[233,1232,913],{"class":643},[233,1234,1236,1239],{"class":235,"line":1235},51,[233,1237,1238],{"class":632},"  try",[233,1240,644],{"class":643},[233,1242,1244,1247,1250,1252,1255,1257,1259,1262,1265,1267,1270],{"class":235,"line":1243},52,[233,1245,1246],{"class":632},"    const",[233,1248,1249],{"class":636}," apiPath",[233,1251,640],{"class":632},[233,1253,1254],{"class":652}," `\u002Flist?bucket=${",[233,1256,998],{"class":636},[233,1258,1001],{"class":652},[233,1260,1261],{"class":636},"BUCKET",[233,1263,1264],{"class":652},"}&prefix=${",[233,1266,1230],{"class":643},[233,1268,1269],{"class":652},"}&limit=1000`",[233,1271,790],{"class":643},[233,1273,1275,1277,1280,1282,1285],{"class":235,"line":1274},53,[233,1276,1246],{"class":632},[233,1278,1279],{"class":636}," apiHost",[233,1281,640],{"class":632},[233,1283,1284],{"class":652}," 'rsf.qiniuapi.com'",[233,1286,1287],{"class":643},"; \n",[233,1289,1291,1293,1296,1298,1300,1302],{"class":235,"line":1290},54,[233,1292,1246],{"class":632},[233,1294,1295],{"class":636}," token",[233,1297,640],{"class":632},[233,1299,972],{"class":632},[233,1301,905],{"class":831},[233,1303,1304],{"class":643},"(apiPath);\n",[233,1306,1308],{"class":235,"line":1307},55,[233,1309,1310],{"class":643},"    \n",[233,1312,1314,1316,1319,1321,1323,1326,1328,1331,1334,1337,1340,1342],{"class":235,"line":1313},56,[233,1315,1246],{"class":632},[233,1317,1318],{"class":636}," response",[233,1320,640],{"class":632},[233,1322,972],{"class":632},[233,1324,1325],{"class":831}," fetch",[233,1327,835],{"class":643},[233,1329,1330],{"class":652},"`https:\u002F\u002F${",[233,1332,1333],{"class":643},"apiHost",[233,1335,1336],{"class":652},"}${",[233,1338,1339],{"class":643},"apiPath",[233,1341,1186],{"class":652},[233,1343,1344],{"class":643},", {\n",[233,1346,1348],{"class":235,"line":1347},57,[233,1349,1350],{"class":643},"      headers: {\n",[233,1352,1354,1357],{"class":235,"line":1353},58,[233,1355,1356],{"class":652},"        'Authorization'",[233,1358,1359],{"class":643},": token,\n",[233,1361,1363,1366,1369],{"class":235,"line":1362},59,[233,1364,1365],{"class":652},"        'Content-Type'",[233,1367,1368],{"class":643},": ",[233,1370,1371],{"class":652},"'application\u002Fx-www-form-urlencoded'\n",[233,1373,1375],{"class":235,"line":1374},60,[233,1376,1377],{"class":643},"      }\n",[233,1379,1381],{"class":235,"line":1380},61,[233,1382,1383],{"class":643},"    });\n",[233,1385,1387],{"class":235,"line":1386},62,[233,1388,613],{"emptyLinePlaceholder":612},[233,1390,1392,1395,1398,1401,1404,1407],{"class":235,"line":1391},63,[233,1393,1394],{"class":632},"    if",[233,1396,1397],{"class":643}," (",[233,1399,1400],{"class":632},"!",[233,1402,1403],{"class":643},"response.ok) ",[233,1405,1406],{"class":632},"return",[233,1408,762],{"class":643},[233,1410,1412],{"class":235,"line":1411},64,[233,1413,613],{"emptyLinePlaceholder":612},[233,1415,1417,1419,1422,1424,1426,1429,1432],{"class":235,"line":1416},65,[233,1418,1246],{"class":632},[233,1420,1421],{"class":636}," data",[233,1423,640],{"class":632},[233,1425,972],{"class":632},[233,1427,1428],{"class":643}," response.",[233,1430,1431],{"class":831},"json",[233,1433,959],{"class":643},[233,1435,1437,1439,1441,1443,1446,1448],{"class":235,"line":1436},66,[233,1438,1394],{"class":632},[233,1440,1397],{"class":643},[233,1442,1400],{"class":632},[233,1444,1445],{"class":643},"data.items) ",[233,1447,1406],{"class":632},[233,1449,762],{"class":643},[233,1451,1453],{"class":235,"line":1452},67,[233,1454,613],{"emptyLinePlaceholder":612},[233,1456,1458,1461],{"class":235,"line":1457},68,[233,1459,1460],{"class":632},"    return",[233,1462,1463],{"class":643}," data.items\n",[233,1465,1467,1470,1473,1475,1478,1480,1483,1486,1489,1492,1494,1497],{"class":235,"line":1466},69,[233,1468,1469],{"class":643},"      .",[233,1471,1472],{"class":831},"filter",[233,1474,835],{"class":643},[233,1476,1477],{"class":843},"item",[233,1479,847],{"class":632},[233,1481,1482],{"class":643}," item.mimeType ",[233,1484,1485],{"class":632},"&&",[233,1487,1488],{"class":643}," item.mimeType.",[233,1490,1491],{"class":831},"startsWith",[233,1493,835],{"class":643},[233,1495,1496],{"class":652},"'image\u002F'",[233,1498,1499],{"class":643},"))\n",[233,1501,1503,1505,1508,1510,1512,1514,1516,1518,1520,1523,1526,1528,1530,1533,1535],{"class":235,"line":1502},70,[233,1504,1469],{"class":643},[233,1506,1507],{"class":831},"map",[233,1509,835],{"class":643},[233,1511,1477],{"class":843},[233,1513,847],{"class":632},[233,1515,927],{"class":652},[233,1517,998],{"class":636},[233,1519,1001],{"class":652},[233,1521,1522],{"class":636},"DOMAIN",[233,1524,1525],{"class":652},"}\u002F${",[233,1527,1477],{"class":643},[233,1529,1001],{"class":652},[233,1531,1532],{"class":643},"key",[233,1534,1186],{"class":652},[233,1536,1161],{"class":643},[233,1538,1540],{"class":235,"line":1539},71,[233,1541,1542],{"class":643},"      \n",[233,1544,1546,1549,1552],{"class":235,"line":1545},72,[233,1547,1548],{"class":643},"  } ",[233,1550,1551],{"class":632},"catch",[233,1553,1554],{"class":643}," (error) {\n",[233,1556,1558,1561,1564,1566,1569,1571,1574],{"class":235,"line":1557},73,[233,1559,1560],{"class":643},"    console.",[233,1562,1563],{"class":831},"error",[233,1565,835],{"class":643},[233,1567,1568],{"class":652},"`拉取目录 ${",[233,1570,1230],{"class":643},[233,1572,1573],{"class":652},"} 失败:`",[233,1575,1576],{"class":643},", error);\n",[233,1578,1580,1582],{"class":235,"line":1579},74,[233,1581,1460],{"class":632},[233,1583,762],{"class":643},[233,1585,1587],{"class":235,"line":1586},75,[233,1588,1589],{"class":643},"  }\n",[233,1591,1593],{"class":235,"line":1592},76,[233,1594,1194],{"class":643},[233,1596,1598],{"class":235,"line":1597},77,[233,1599,613],{"emptyLinePlaceholder":612},[233,1601,1603],{"class":235,"line":1602},78,[233,1604,618],{"class":591},[233,1606,1608],{"class":235,"line":1607},79,[233,1609,1610],{"class":591},"\u002F\u002F 5. 代理获取图片并注入跨域头 (核心新增逻辑)\n",[233,1612,1614],{"class":235,"line":1613},80,[233,1615,618],{"class":591},[233,1617,1619,1621,1623,1626,1628,1631],{"class":235,"line":1618},81,[233,1620,899],{"class":632},[233,1622,902],{"class":632},[233,1624,1625],{"class":831}," proxyImage",[233,1627,835],{"class":643},[233,1629,1630],{"class":843},"imageUrl",[233,1632,913],{"class":643},[233,1634,1636,1638],{"class":235,"line":1635},82,[233,1637,1238],{"class":632},[233,1639,644],{"class":643},[233,1641,1643],{"class":235,"line":1642},83,[233,1644,1645],{"class":591},"    \u002F\u002F 边缘接入点出面去你的 CDN 拿图\n",[233,1647,1649,1651,1653,1655,1657,1659],{"class":235,"line":1648},84,[233,1650,1246],{"class":632},[233,1652,1318],{"class":636},[233,1654,640],{"class":632},[233,1656,972],{"class":632},[233,1658,1325],{"class":831},[233,1660,1661],{"class":643},"(imageUrl, {\n",[233,1663,1665],{"class":235,"line":1664},85,[233,1666,1350],{"class":643},[233,1668,1670,1673,1675],{"class":235,"line":1669},86,[233,1671,1672],{"class":652},"        \"User-Agent\"",[233,1674,1368],{"class":643},[233,1676,1677],{"class":652},"\"Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64) EdgeOne-Proxy\"\n",[233,1679,1681],{"class":235,"line":1680},87,[233,1682,1377],{"class":643},[233,1684,1686],{"class":235,"line":1685},88,[233,1687,1383],{"class":643},[233,1689,1691],{"class":235,"line":1690},89,[233,1692,613],{"emptyLinePlaceholder":612},[233,1694,1696,1698],{"class":235,"line":1695},90,[233,1697,1394],{"class":632},[233,1699,1700],{"class":643}," (response.ok) {\n",[233,1702,1704],{"class":235,"line":1703},91,[233,1705,1706],{"class":591},"      \u002F\u002F 拿到图片后，重写响应头，强行允许跨域\n",[233,1708,1710,1713,1716,1718,1720,1723],{"class":235,"line":1709},92,[233,1711,1712],{"class":632},"      const",[233,1714,1715],{"class":636}," newHeaders",[233,1717,640],{"class":632},[233,1719,953],{"class":632},[233,1721,1722],{"class":831}," Headers",[233,1724,1725],{"class":643},"(response.headers);\n",[233,1727,1729,1732,1735,1737,1740,1742,1745],{"class":235,"line":1728},93,[233,1730,1731],{"class":643},"      newHeaders.",[233,1733,1734],{"class":831},"set",[233,1736,835],{"class":643},[233,1738,1739],{"class":652},"\"Access-Control-Allow-Origin\"",[233,1741,688],{"class":643},[233,1743,1744],{"class":652},"\"*\"",[233,1746,1161],{"class":643},[233,1748,1750,1752,1754,1756,1759,1761,1764,1767],{"class":235,"line":1749},94,[233,1751,1731],{"class":643},[233,1753,1734],{"class":831},[233,1755,835],{"class":643},[233,1757,1758],{"class":652},"\"Cache-Control\"",[233,1760,688],{"class":643},[233,1762,1763],{"class":652},"\"no-cache\"",[233,1765,1766],{"class":643},"); ",[233,1768,1769],{"class":591},"\u002F\u002F 告诉浏览器不要缓存当前API链接，以免下次拿不到新图\n",[233,1771,1773],{"class":235,"line":1772},95,[233,1774,613],{"emptyLinePlaceholder":612},[233,1776,1778],{"class":235,"line":1777},96,[233,1779,1780],{"class":591},"      \u002F\u002F 返回 200 状态码和真实图片数据流\n",[233,1782,1784,1787,1789,1792],{"class":235,"line":1783},97,[233,1785,1786],{"class":632},"      return",[233,1788,953],{"class":632},[233,1790,1791],{"class":831}," Response",[233,1793,1794],{"class":643},"(response.body, {\n",[233,1796,1798,1801,1804],{"class":235,"line":1797},98,[233,1799,1800],{"class":643},"        status: ",[233,1802,1803],{"class":636},"200",[233,1805,667],{"class":643},[233,1807,1809],{"class":235,"line":1808},99,[233,1810,1811],{"class":643},"        headers: newHeaders\n",[233,1813,1815],{"class":235,"line":1814},100,[233,1816,1817],{"class":643},"      });\n",[233,1819,1821],{"class":235,"line":1820},101,[233,1822,1823],{"class":643},"    }\n",[233,1825,1827],{"class":235,"line":1826},102,[233,1828,1310],{"class":643},[233,1830,1832],{"class":235,"line":1831},103,[233,1833,1834],{"class":591},"    \u002F\u002F 如果图片代理失败，降级回 302 重定向\n",[233,1836,1838,1840,1843,1846,1849,1852],{"class":235,"line":1837},104,[233,1839,1460],{"class":632},[233,1841,1842],{"class":643}," Response.",[233,1844,1845],{"class":831},"redirect",[233,1847,1848],{"class":643},"(imageUrl, ",[233,1850,1851],{"class":636},"302",[233,1853,1161],{"class":643},[233,1855,1857,1859,1861],{"class":235,"line":1856},105,[233,1858,1548],{"class":643},[233,1860,1551],{"class":632},[233,1862,1863],{"class":643}," (e) {\n",[233,1865,1867],{"class":235,"line":1866},106,[233,1868,1869],{"class":591},"    \u002F\u002F 网络异常，降级回 302 重定向\n",[233,1871,1873,1875,1877,1879,1881,1883],{"class":235,"line":1872},107,[233,1874,1460],{"class":632},[233,1876,1842],{"class":643},[233,1878,1845],{"class":831},[233,1880,1848],{"class":643},[233,1882,1851],{"class":636},[233,1884,1161],{"class":643},[233,1886,1888],{"class":235,"line":1887},108,[233,1889,1589],{"class":643},[233,1891,1893],{"class":235,"line":1892},109,[233,1894,1194],{"class":643},[233,1896,1898],{"class":235,"line":1897},110,[233,1899,613],{"emptyLinePlaceholder":612},[233,1901,1903],{"class":235,"line":1902},111,[233,1904,618],{"class":591},[233,1906,1908],{"class":235,"line":1907},112,[233,1909,1910],{"class":591},"\u002F\u002F 6. 主路由逻辑\n",[233,1912,1914],{"class":235,"line":1913},113,[233,1915,618],{"class":591},[233,1917,1919,1921,1923,1926,1928,1931],{"class":235,"line":1918},114,[233,1920,899],{"class":632},[233,1922,902],{"class":632},[233,1924,1925],{"class":831}," handleRequest",[233,1927,835],{"class":643},[233,1929,1930],{"class":843},"request",[233,1932,913],{"class":643},[233,1934,1936,1938,1941,1943,1945,1948],{"class":235,"line":1935},115,[233,1937,919],{"class":632},[233,1939,1940],{"class":636}," url",[233,1942,640],{"class":632},[233,1944,953],{"class":632},[233,1946,1947],{"class":831}," URL",[233,1949,1950],{"class":643},"(request.url);\n",[233,1952,1954,1956,1959,1961],{"class":235,"line":1953},116,[233,1955,919],{"class":632},[233,1957,1958],{"class":636}," route",[233,1960,640],{"class":632},[233,1962,1963],{"class":643}," url.pathname;\n",[233,1965,1967],{"class":235,"line":1966},117,[233,1968,613],{"emptyLinePlaceholder":612},[233,1970,1972],{"class":235,"line":1971},118,[233,1973,1974],{"class":591},"  \u002F\u002F 初始化或更新缓存\n",[233,1976,1978,1981,1984,1987,1990,1993,1995,1998,2000,2003,2006,2009,2012,2014,2016,2019,2021,2023,2025],{"class":235,"line":1977},119,[233,1979,1980],{"class":632},"  if",[233,1982,1983],{"class":643}," (Date.",[233,1985,1986],{"class":831},"now",[233,1988,1989],{"class":643},"() ",[233,1991,1992],{"class":632},"-",[233,1994,782],{"class":643},[233,1996,1997],{"class":632},">",[233,1999,798],{"class":636},[233,2001,2002],{"class":632}," ||",[233,2004,2005],{"class":643}," pcImages.",[233,2007,2008],{"class":636},"length",[233,2010,2011],{"class":632}," ===",[233,2013,787],{"class":636},[233,2015,2002],{"class":632},[233,2017,2018],{"class":643}," mobileImages.",[233,2020,2008],{"class":636},[233,2022,2011],{"class":632},[233,2024,787],{"class":636},[233,2026,913],{"class":643},[233,2028,2030,2033],{"class":235,"line":2029},120,[233,2031,2032],{"class":632},"    try",[233,2034,644],{"class":643},[233,2036,2038,2040,2043,2046,2048,2051,2054,2056,2058,2061,2063,2066],{"class":235,"line":2037},121,[233,2039,1712],{"class":632},[233,2041,2042],{"class":643}," [",[233,2044,2045],{"class":636},"newPc",[233,2047,688],{"class":643},[233,2049,2050],{"class":636},"newMobile",[233,2052,2053],{"class":643},"] ",[233,2055,759],{"class":632},[233,2057,972],{"class":632},[233,2059,2060],{"class":636}," Promise",[233,2062,1001],{"class":643},[233,2064,2065],{"class":831},"all",[233,2067,2068],{"class":643},"([\n",[233,2070,2072,2075,2077,2079,2081,2084],{"class":235,"line":2071},122,[233,2073,2074],{"class":831},"        fetchImagesFromQiniu",[233,2076,835],{"class":643},[233,2078,998],{"class":636},[233,2080,1001],{"class":643},[233,2082,2083],{"class":636},"PC_PREFIX",[233,2085,2086],{"class":643},"),\n",[233,2088,2090,2092,2094,2096,2098,2101],{"class":235,"line":2089},123,[233,2091,2074],{"class":831},[233,2093,835],{"class":643},[233,2095,998],{"class":636},[233,2097,1001],{"class":643},[233,2099,2100],{"class":636},"MOBILE_PREFIX",[233,2102,2103],{"class":643},")\n",[233,2105,2107],{"class":235,"line":2106},124,[233,2108,2109],{"class":643},"      ]);\n",[233,2111,2113],{"class":235,"line":2112},125,[233,2114,1542],{"class":643},[233,2116,2118,2121,2124,2126,2129,2131,2134,2136],{"class":235,"line":2117},126,[233,2119,2120],{"class":632},"      if",[233,2122,2123],{"class":643}," (newPc.",[233,2125,2008],{"class":636},[233,2127,2128],{"class":632}," >",[233,2130,787],{"class":636},[233,2132,2133],{"class":643},") pcImages ",[233,2135,759],{"class":632},[233,2137,2138],{"class":643}," newPc;\n",[233,2140,2142,2144,2147,2149,2151,2153,2156,2158],{"class":235,"line":2141},127,[233,2143,2120],{"class":632},[233,2145,2146],{"class":643}," (newMobile.",[233,2148,2008],{"class":636},[233,2150,2128],{"class":632},[233,2152,787],{"class":636},[233,2154,2155],{"class":643},") mobileImages ",[233,2157,759],{"class":632},[233,2159,2160],{"class":643}," newMobile;\n",[233,2162,2164,2167,2169,2172,2174],{"class":235,"line":2163},128,[233,2165,2166],{"class":643},"      lastCheckTime ",[233,2168,759],{"class":632},[233,2170,2171],{"class":643}," Date.",[233,2173,1986],{"class":831},[233,2175,959],{"class":643},[233,2177,2179,2182,2184],{"class":235,"line":2178},129,[233,2180,2181],{"class":643},"    } ",[233,2183,1551],{"class":632},[233,2185,1863],{"class":643},[233,2187,2189,2192,2194,2196,2199],{"class":235,"line":2188},130,[233,2190,2191],{"class":643},"      console.",[233,2193,1563],{"class":831},[233,2195,835],{"class":643},[233,2197,2198],{"class":652},"\"更新列表失败，暂时使用旧缓存\"",[233,2200,1161],{"class":643},[233,2202,2204],{"class":235,"line":2203},131,[233,2205,1823],{"class":643},[233,2207,2209],{"class":235,"line":2208},132,[233,2210,1589],{"class":643},[233,2212,2214],{"class":235,"line":2213},133,[233,2215,613],{"emptyLinePlaceholder":612},[233,2217,2219],{"class":235,"line":2218},134,[233,2220,2221],{"class":591},"  \u002F\u002F --- 处理电脑壁纸 ---\n",[233,2223,2225,2227,2230,2233,2236],{"class":235,"line":2224},135,[233,2226,1980],{"class":632},[233,2228,2229],{"class":643}," (route ",[233,2231,2232],{"class":632},"===",[233,2234,2235],{"class":652}," '\u002Fapi'",[233,2237,913],{"class":643},[233,2239,2241,2243,2246,2248,2250,2252,2255,2257,2259,2261,2263,2266,2269,2272],{"class":235,"line":2240},136,[233,2242,1394],{"class":632},[233,2244,2245],{"class":643}," (pcImages.",[233,2247,2008],{"class":636},[233,2249,2011],{"class":632},[233,2251,787],{"class":636},[233,2253,2254],{"class":643},") ",[233,2256,1406],{"class":632},[233,2258,953],{"class":632},[233,2260,1791],{"class":831},[233,2262,835],{"class":643},[233,2264,2265],{"class":652},"\"初始化中...\"",[233,2267,2268],{"class":643},", {status: ",[233,2270,2271],{"class":636},"503",[233,2273,872],{"class":643},[233,2275,2277,2279,2282,2284,2287,2290,2293,2296,2298,2301,2303,2305],{"class":235,"line":2276},137,[233,2278,1246],{"class":632},[233,2280,2281],{"class":636}," randomImg",[233,2283,640],{"class":632},[233,2285,2286],{"class":643}," pcImages[Math.",[233,2288,2289],{"class":831},"floor",[233,2291,2292],{"class":643},"(Math.",[233,2294,2295],{"class":831},"random",[233,2297,1989],{"class":643},[233,2299,2300],{"class":632},"*",[233,2302,2005],{"class":643},[233,2304,2008],{"class":636},[233,2306,2307],{"class":643},")];\n",[233,2309,2311],{"class":235,"line":2310},138,[233,2312,2313],{"class":591},"    \u002F\u002F 调用代理函数，直接返回图片流\n",[233,2315,2317,2319,2321,2323],{"class":235,"line":2316},139,[233,2318,1460],{"class":632},[233,2320,972],{"class":632},[233,2322,1625],{"class":831},[233,2324,2325],{"class":643},"(randomImg);\n",[233,2327,2329],{"class":235,"line":2328},140,[233,2330,1589],{"class":643},[233,2332,2334],{"class":235,"line":2333},141,[233,2335,613],{"emptyLinePlaceholder":612},[233,2337,2339],{"class":235,"line":2338},142,[233,2340,2341],{"class":591},"  \u002F\u002F --- 处理手机壁纸 ---\n",[233,2343,2345,2347,2349,2351,2354],{"class":235,"line":2344},143,[233,2346,1980],{"class":632},[233,2348,2229],{"class":643},[233,2350,2232],{"class":632},[233,2352,2353],{"class":652}," '\u002Fm-api'",[233,2355,913],{"class":643},[233,2357,2359,2361,2364,2366,2368,2370,2372,2374,2376,2378,2380,2382,2384,2386],{"class":235,"line":2358},144,[233,2360,1394],{"class":632},[233,2362,2363],{"class":643}," (mobileImages.",[233,2365,2008],{"class":636},[233,2367,2011],{"class":632},[233,2369,787],{"class":636},[233,2371,2254],{"class":643},[233,2373,1406],{"class":632},[233,2375,953],{"class":632},[233,2377,1791],{"class":831},[233,2379,835],{"class":643},[233,2381,2265],{"class":652},[233,2383,2268],{"class":643},[233,2385,2271],{"class":636},[233,2387,872],{"class":643},[233,2389,2391,2393,2395,2397,2400,2402,2404,2406,2408,2410,2412,2414],{"class":235,"line":2390},145,[233,2392,1246],{"class":632},[233,2394,2281],{"class":636},[233,2396,640],{"class":632},[233,2398,2399],{"class":643}," mobileImages[Math.",[233,2401,2289],{"class":831},[233,2403,2292],{"class":643},[233,2405,2295],{"class":831},[233,2407,1989],{"class":643},[233,2409,2300],{"class":632},[233,2411,2018],{"class":643},[233,2413,2008],{"class":636},[233,2415,2307],{"class":643},[233,2417,2419],{"class":235,"line":2418},146,[233,2420,2313],{"class":591},[233,2422,2424,2426,2428,2430],{"class":235,"line":2423},147,[233,2425,1460],{"class":632},[233,2427,972],{"class":632},[233,2429,1625],{"class":831},[233,2431,2325],{"class":643},[233,2433,2435],{"class":235,"line":2434},148,[233,2436,1589],{"class":643},[233,2438,2440],{"class":235,"line":2439},149,[233,2441,613],{"emptyLinePlaceholder":612},[233,2443,2445,2447,2449,2451,2453,2456],{"class":235,"line":2444},150,[233,2446,1167],{"class":632},[233,2448,953],{"class":632},[233,2450,1791],{"class":831},[233,2452,835],{"class":643},[233,2454,2455],{"class":652},"\"API 正常运行。电脑壁纸请访问 \u002Fapi，手机壁纸请访问 \u002Fm-api\"",[233,2457,2458],{"class":643},", { \n",[233,2460,2462,2465,2467],{"class":235,"line":2461},151,[233,2463,2464],{"class":643},"    status: ",[233,2466,1803],{"class":636},[233,2468,656],{"class":643},[233,2470,2472,2475,2478,2480,2483],{"class":235,"line":2471},152,[233,2473,2474],{"class":643},"    headers: { ",[233,2476,2477],{"class":652},"\"Content-Type\"",[233,2479,1368],{"class":643},[233,2481,2482],{"class":652},"\"text\u002Fhtml;charset=UTF-8\"",[233,2484,2485],{"class":643}," } \n",[233,2487,2489],{"class":235,"line":2488},153,[233,2490,2491],{"class":643},"  });\n",[233,2493,2495],{"class":235,"line":2494},154,[233,2496,1194],{"class":643},[64,2498,2500],{"id":2499},"_54-新增触发规则","5.4 新增触发规则",[25,2502,2503,2506,2519],{},[28,2504,2505],{},"函数发布完成后进入触发规则管理页面，新增自定义匹配规则；",[28,2507,2508,2509,408,2512,2515,2516,2518],{},"匹配路径配置：",[230,2510,2511],{},"^\u002Fapi.*",[230,2513,2514],{},"^\u002Fm-api.*","，匹配域名选择已接入业务站点域名",[230,2517,483],{},"；",[28,2520,2521,2522,2525,2526,2529],{},"保存规则，等待 ",[20,2523,2524],{},"2 ~ 5 min"," 完成全网边缘接入点配置同步。\n",[436,2527],{"alt":228,"src":2528},"https:\u002F\u002Fimg.nw177.cn\u002Fblog\u002F2026\u002F07\u002F14\u002F1783959437810.avif",[436,2530],{"alt":228,"src":2531},"https:\u002F\u002Fimg.nw177.cn\u002Fblog\u002F2026\u002F07\u002F14\u002F1783959391699.avif",[57,2533],{},[11,2535,2537],{"id":2536},"_6-全维度功能测试验证","6 全维度功能测试验证",[64,2539,2541],{"id":2540},"_61-基础访问测试","6.1 基础访问测试",[25,2543,2544,2557,2566],{},[28,2545,2546,2547,2550,2551,2553,2554],{},"请求 ",[230,2548,2549],{},"https:\u002F\u002Fapi.img.你的备案域名.com\u002Fapi","，多次刷新随机返回 ",[20,2552,22],{}," 宽屏壁纸二进制图片；\n",[436,2555],{"alt":228,"src":2556},"https:\u002F\u002Fimg.nw177.cn\u002Fblog\u002F2026\u002F07\u002F14\u002F1783959805765.avif",[28,2558,2546,2559,2562,2563],{},[230,2560,2561],{},"https:\u002F\u002Fapi.img.你的备案域名.com\u002Fm-api","，随机返回移动端竖屏适配图片；\n",[436,2564],{"alt":228,"src":2565},"https:\u002F\u002Fimg.nw177.cn\u002Fblog\u002F2026\u002F07\u002F14\u002F1783959897846.avif",[28,2567,2568,2569,2572,2573,2575],{},"非法路由如 ",[230,2570,2571],{},"\u002Ftest"," 访问，接口返回 ",[20,2574,94],{}," 文本提示，路由匹配逻辑正常。",[64,2577,2579],{"id":2578},"_62-缓存机制测试","6.2 缓存机制测试",[25,2581,2582,2589,2595],{},[28,2583,2584,2585,2588],{},"浏览器开发者工具查看响应头，携带 ",[230,2586,2587],{},"Cache-Control: public,max-age=86400"," 缓存标识；",[28,2590,2591,2592,2594],{},"同一区域重复访问同一张图片，",[20,2593,50],{}," 边缘接入点命中本地缓存，无额外存储回源请求；",[28,2596,2597,2598,2600],{},"高频调用场景下，持续削减七牛云 \u002F ",[20,2599,87],{}," 对象存储下行流量，长期降低存储计费成本。",[64,2602,2604],{"id":2603},"_63-跨域测试","6.3 跨域测试",[25,2606,2607,2613],{},[28,2608,2609,2610,2612],{},"前端页面通过 fetch、axios 直接调用接口，浏览器无 ",[20,2611,36],{}," 跨域拦截报错；",[28,2614,2615,2618,2619,2622],{},[20,2616,2617],{},"OPTIONS"," 预检请求返回 ",[20,2620,2621],{},"204"," 状态码，完整携带跨域允许头，兼容各类前端请求场景。",[64,2624,2626],{"id":2625},"_64-异常降级测试","6.4 异常降级测试",[25,2628,2629,2632,2638],{},[28,2630,2631],{},"目标图库目录未上传任何图片，接口自动返回配置兜底占位图；",[28,2633,2634,2635,2637],{},"存储 ",[20,2636,43],{}," 配置错误、存储接口网络超时，捕获异常后切换兜底图片；",[28,2639,2634,2640,2642],{},[20,2641,155],{}," 域名失效、图片资源被删除，统一走降级逻辑，页面无空白崩溃。",[57,2644],{},[11,2646,2648],{"id":2647},"_7-当前代码现存缺陷-可落地迭代优化方案","7 当前代码现存缺陷 & 可落地迭代优化方案",[64,2650,2652],{"id":2651},"_71-现有代码局限","7.1 现有代码局限",[25,2654,2655,2661,2671,2674,2681],{},[28,2656,2657,2658,2660],{},"内存单实例缓存短板：",[20,2659,50],{}," 边缘单实例内存缓存不持久，接入点扩容、实例重启后缓存数据清空，无分布式持久化缓存支撑；",[28,2662,2663,2664,2667,2668,2670],{},"图片数量上限约束：七牛 list 接口单次限制返回 ",[20,2665,2666],{},"1000"," 条文件，图库图片总量超过 ",[20,2669,2666],{}," 张时无法全量随机抽取；",[28,2672,2673],{},"缺少图片尺寸过滤逻辑：仅通过文件后缀筛选资源，无法根据宽高比例筛选适配图片；",[28,2675,2676,2677,2680],{},"无接口限流防护：未增加 ",[20,2678,2679],{},"IP"," 访问频次限制，恶意高频刷接口会持续消耗存储回源流量；",[28,2682,2683],{},"日志体系简陋：仅基础控制台打印错误信息，无结构化日志上报，无法统计缓存命中率、接口访问量。",[64,2685,2687],{"id":2686},"_72-落地迭代优化方案","7.2 落地迭代优化方案",[25,2689,2690,2697,2703,2706,2713,2719,2722],{},[28,2691,2692,2693,2696],{},"接入 ",[20,2694,2695],{},"EdgeOne KV"," 分布式缓存，将文件列表持久化缓存，减少重复请求存储列表接口；",[28,2698,2699,2700,2702],{},"递归分页拉取存储文件列表，突破单轮 ",[20,2701,2666],{}," 条文件上限，支持上万张图库全量随机；",[28,2704,2705],{},"扩展接口传参能力，支持前端传入宽高比例参数，过滤对应尺寸图片资源；",[28,2707,2708,2709,2712],{},"基于客户端 ",[20,2710,2711],{},"IP + KV"," 存储实现分钟级限流，拦截恶意高频刷接口行为；",[28,2714,2715,2716,2718],{},"对接 ",[20,2717,50],{}," 日志服务，结构化记录缓存命中、回源失败、访问频次等运营数据；",[28,2720,2721],{},"增加动态缓存时长参数，前端可按需传入 max-age 控制边缘缓存有效期；",[28,2723,2724,2725,408,2727,2729,2730,2732],{},"抽离签名逻辑，兼容七牛、",[20,2726,430],{},[20,2728,426],{},"、MinIO 多类 ",[20,2731,87],{}," 标准存储一键切换。",[57,2734],{},[11,2736,2738],{"id":2737},"_8-全文总结","8 全文总结",[64,2740,2742],{"id":2741},"_81-方案适用场景","8.1 方案适用场景",[25,2744,2745,2748,2754,2757],{},[28,2746,2747],{},"Hexo \u002F VitePress 等纯静态博客、个人 \u002F 企业静态站点，需要随机封面、随机壁纸 API；",[28,2749,2750,2751,2753],{},"业务需要 ",[20,2752,22],{},"、移动端两套完全隔离的图片资源池，区分设备展示不同尺寸图片；",[28,2755,2756],{},"无后端服务器，希望依靠边缘计算实现轻量图片接口，降低服务器运维成本；",[28,2758,2759],{},"希望隐藏对象存储真实域名，减少源站流量消耗，控制存储服务计费。",[64,2761,2763],{"id":2762},"_82-整体工程优势","8.2 整体工程优势",[25,2765,2766,2772,2775,2778,2784],{},[28,2767,2768,2769,2771],{},"零后端服务部署，仅依赖 ",[20,2770,50],{}," 边缘函数，服务器运维成本几乎为 0；",[28,2773,2774],{},"全球边缘接入点分发图片资源，图片加载速度优于前端直连对象存储；",[28,2776,2777],{},"鉴权密钥存放边缘环境变量，前端无法获取存储地址与鉴权信息，数据安全性更高；",[28,2779,2780,2781,2783],{},"统一封装跨域、缓存、异常降级逻辑，一套代码兼容全部 ",[20,2782,87],{}," 标准对象存储；",[28,2785,2786],{},"完整工程闭环：业务需求 → 方案对比 → 架构设计 → 源码拆解 → 部署实操 → 全维度测试 → 迭代优化，所有代码配置可直接复现落地。",[16,2788,2789],{},"Created with ❤️ by 张萌萌",[2791,2792,2793],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .snhLl, html code.shiki .snhLl{--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold}",{"title":228,"searchDepth":242,"depth":242,"links":2795},[2796,2797,2802,2806,2807,2813,2819,2823],{"id":13,"depth":242,"text":14},{"id":61,"depth":242,"text":62,"children":2798},[2799,2800,2801],{"id":66,"depth":248,"text":67},{"id":98,"depth":248,"text":99},{"id":204,"depth":248,"text":205},{"id":216,"depth":242,"text":217,"children":2803},[2804,2805],{"id":220,"depth":248,"text":221},{"id":348,"depth":248,"text":349},{"id":382,"depth":242,"text":383},{"id":456,"depth":242,"text":457,"children":2808},[2809,2810,2811,2812],{"id":460,"depth":248,"text":461},{"id":521,"depth":248,"text":522},{"id":549,"depth":248,"text":550},{"id":2499,"depth":248,"text":2500},{"id":2536,"depth":242,"text":2537,"children":2814},[2815,2816,2817,2818],{"id":2540,"depth":248,"text":2541},{"id":2578,"depth":248,"text":2579},{"id":2603,"depth":248,"text":2604},{"id":2625,"depth":248,"text":2626},{"id":2647,"depth":242,"text":2648,"children":2820},[2821,2822],{"id":2651,"depth":248,"text":2652},{"id":2686,"depth":248,"text":2687},{"id":2737,"depth":242,"text":2738,"children":2824},[2825,2826],{"id":2741,"depth":248,"text":2742},{"id":2762,"depth":248,"text":2763},"Blog",null,"2026-07-13 21:25:48",false,"md","https:\u002F\u002Fimg.nw177.cn\u002Fblog\u002F2026\u002F07\u002F14\u002F1783960387193.avif",{"published":2829},"\u002Fblog\u002F10-技术专栏\u002F40-WebsiteBuilding\u002F07-腾讯云-EdgeOne-边缘函数实现七牛-S3-随机图床-API",{"title":5,"description":5},"blog\u002F10-技术专栏\u002F40-WebsiteBuilding\u002F07-腾讯云 EdgeOne 边缘函数实现七牛&S3 随机图床 API",[50,2838,2839],"七牛云","图床","c8GhVLzbb5IvlJuoc7DCJmfZgLBHnamziD71uO4snUE",[2842,2846,2850,2854,2857,2860,2864,2867,2871,2875,2876,2880,2884,2888,2892,2896,2900,2904,2908,2911,2915,2919,2923,2927,2930,2934,2938,2942,2946,2950,2954,2958,2962,2966,2970,2974,2978,2981,2985,2989,2993,2997,3001,3004,3007,3010,3013,3016,3019,3022,3025,3028,3031,3034,3037,3040,3043,3046,3049,3052,3055],{"path":2843,"title":2844,"date":2845},"\u002Fblog\u002F10-技术专栏\u002F20-network\u002F16.IPv6与DNS的分手协议","IPv6 与 DNS 的分手协议","2026-10-02",{"path":2847,"title":2848,"date":2849},"\u002Fblog\u002F10-技术专栏\u002F50-AI\u002F04.我的-AI-入坑记","我的 AI 入坑记","2026-09-24",{"path":2851,"title":2852,"date":2853},"\u002Fblog\u002F10-技术专栏\u002F50-AI\u002F01.用-Docker-部署-Ollama-与-Open-WebUI-搭建本地大模型","用 Docker 部署 Ollama 与 Open WebUI 搭建本地大模型","2026-09-23",{"path":2855,"title":2856,"date":2853},"\u002Fblog\u002F10-技术专栏\u002F50-AI\u002F02.用-New-API-搭建统一-LLM-网关与-Lucky-反代外网访问","用 New API 搭建统一 LLM 网关与 Lucky 反代外网访问",{"path":2858,"title":2859,"date":2853},"\u002Fblog\u002F10-技术专栏\u002F50-AI\u002F03.用-Dify-搭建本地知识库让-AI-读懂你写的博客","用 Dify 搭建本地知识库，让 AI 读懂你写的博客",{"path":2861,"title":2862,"date":2863},"\u002Fblog\u002F20-生活碎片\u002F03-2026年秋季计划","2026 年秋季计划","2026-09-19",{"path":2865,"title":2866,"date":2863},"\u002Fblog\u002F30-学习笔记\u002F02.Python入门书单","Python 入门书单：从第一行代码到写出真正的程序",{"path":2868,"title":2869,"date":2870},"\u002Fblog\u002F10-技术专栏\u002F40-WebsiteBuilding\u002F09-Cloudflare-低延迟接入方案","Cloudflare 低延迟接入方案","2026-07-22 03:17:28",{"path":2872,"title":2873,"date":2874},"\u002Fblog\u002F10-技术专栏\u002F40-WebsiteBuilding\u002F08-Cloudflare-ImgBed-免费私有图床完整部署手册","Cloudflare ImgBed 免费私有图床完整部署手册","2026-07-19 02:09:08",{"path":2834,"title":5,"date":2829},{"path":2877,"title":2878,"date":2879},"\u002Fblog\u002F10-技术专栏\u002F40-WebsiteBuilding\u002F06-腾讯-EdgeOne-部署-Twikoo-评论系统指南","腾讯EdgeOne部署Twikoo评论系统指南","2026-06-14 17:41:11",{"path":2881,"title":2882,"date":2883},"\u002Fblog\u002F10-技术专栏\u002F40-WebsiteBuilding\u002F05-OpenList-接入-S3-对象存储完整使用教程","OpenList 接入 S3 对象存储完整使用教程","2026-06-11 13:08:07",{"path":2885,"title":2886,"date":2887},"\u002Fblog\u002F10-技术专栏\u002F40-WebsiteBuilding\u002F04-Cloudflare-R2-图床与全球加速方案","Cloudflare R2 图床与全球加速方案","2026-06-09 13:07:35",{"path":2889,"title":2890,"date":2891},"\u002Fblog\u002F10-技术专栏\u002F40-WebsiteBuilding\u002F03-免费图床与CDN加速方案","免费图床与 CDN 加速方案","2026-06-09",{"path":2893,"title":2894,"date":2895},"\u002Fblog\u002F10-技术专栏\u002F40-WebsiteBuilding\u002F02-零基础优雅搭建静态博客全教程","零基础优雅搭建静态博客全教程","2026-06-04",{"path":2897,"title":2898,"date":2899},"\u002Fblog\u002F10-技术专栏\u002F40-WebsiteBuilding\u002F01-远古产物—博客","赛博空间的私人岛屿：博客架构与风格美学","2026-06-03",{"path":2901,"title":2902,"date":2903},"\u002Fblog\u002F10-技术专栏\u002F20-network\u002F15.关于NAT回流与内网域名直连的终极指南","关于 NAT 回流与内网域名直连的终极指南","2026-05-13",{"path":2905,"title":2906,"date":2907},"\u002Fblog\u002F10-技术专栏\u002F20-network\u002F14.飞牛安全访问与Lucky反代雷池防护","飞牛安全访问与 Lucky 反代雷池防护","2026-02-03",{"path":2909,"title":2910,"date":2907},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F18.一键DD纯净系统脚本","一键 DD 纯净系统脚本",{"path":2912,"title":2913,"date":2914},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F17.Ventoy多系统启动盘制作与使用全指南","Ventoy 多系统启动盘制作与使用全指南","2026-02-02",{"path":2916,"title":2917,"date":2918},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F16.Emby元数据匹配与中文命名规范","Emby 元数据匹配与中文命名规范","2026-02-01",{"path":2920,"title":2921,"date":2922},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F15.基于PVE系统安装LXC-debian","基于 PVE 系统安装 LXC-debian","2026-01-19",{"path":2924,"title":2925,"date":2926},"\u002Fblog\u002F10-技术专栏\u002F20-network\u002F13.Lucky反向代理终极指南","Lucky 反向代理终极指南","2026-01-16",{"path":2928,"title":2929,"date":2926},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F14.OEC盒子Armbian刷机指南","OEC 盒子 Armbian 刷机指南",{"path":2931,"title":2932,"date":2933},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F13.oec-fnOS安装","OEC-Turbo (RK3566) 安装飞牛 OS","2026-01-15",{"path":2935,"title":2936,"date":2937},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F12.新的篇章，debian12的配置","新的篇章，debian12 的配置","2026-01-14",{"path":2939,"title":2940,"date":2941},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F11.飞牛OS安装后必要配置","飞牛 OS 安装后必要配置","2026-01-06",{"path":2943,"title":2944,"date":2945},"\u002Fblog\u002F10-技术专栏\u002F10-docker\u002F11.NAS-导航页的终极形态","告别繁琐配置：NAS 导航页的终极形态 —— 从 Sun-Panel 到 FlatNAS","2026-01-05",{"path":2947,"title":2948,"date":2949},"\u002Fblog\u002F10-技术专栏\u002F10-docker\u002F10.LogVar-弹幕-API-部署指南","LogVar 弹幕 API  (纯本地缓存版) 部署指南","2025-12-30",{"path":2951,"title":2952,"date":2953},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F10.基于Lucky与QMediaSync的飞牛远程媒体访问","基于 Lucky 与 QMediaSync 的飞牛远程媒体访问","2025-12-26",{"path":2955,"title":2956,"date":2957},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F09.新的篇章，PVE虚拟机","新的篇章，PVE虚拟机","2025-12-21",{"path":2959,"title":2960,"date":2961},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F08.Linux系统，音响有底噪","Linux 系统，音响有底噪怎么办？","2025-12-17",{"path":2963,"title":2964,"date":2965},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F07.飞牛OS的安装","飞牛 OS 的安装","2025-12-14",{"path":2967,"title":2968,"date":2969},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F06.Debian13换源","Debian13 换源","2025-11-29",{"path":2971,"title":2972,"date":2973},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F05.Kodi-CoreELEC安装指南","Kodi & CoreELEC 安装指南","2025-11-21",{"path":2975,"title":2976,"date":2977},"\u002Fblog\u002F10-技术专栏\u002F10-docker\u002F09.兰空图床和高清图标库","兰空图床和高清图标库","2025-11-15",{"path":2979,"title":2980,"date":2977},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F04.N1盒子Armbian刷机与配置","N1 盒子 Armbian 刷机与配置",{"path":2982,"title":2983,"date":2984},"\u002Fblog\u002F10-技术专栏\u002F10-docker\u002F08.你是否需要一个图床？","你是否需要一个图床？","2025-11-14",{"path":2986,"title":2987,"date":2988},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F03.飞牛NAS第三方应用商店安装","飞牛 NAS 第三方应用商店 (FnDepot) 安装指南","2025-10-13",{"path":2990,"title":2991,"date":2992},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F02.Hills播放器-Windows-安卓","Hills 播放器（Windows + 安卓）","2025-09-24",{"path":2994,"title":2995,"date":2996},"\u002Fblog\u002F10-技术专栏\u002F30-Linux\u002F01.一行代码降低服务器功耗","一行代码降低服务器功耗","2025-08-19",{"path":2998,"title":2999,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F10-docker\u002F01.容器-docker-docker-compose","容器 & docker & docker-compose","2025-08-05",{"path":3002,"title":3003,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F10-docker\u002F02.容器项目-传输类","容器项目&传输类",{"path":3005,"title":3006,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F10-docker\u002F03.容器项目-相册类","容器项目&相册类",{"path":3008,"title":3009,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F10-docker\u002F04.容器项目-媒体类","容器项目&媒体类",{"path":3011,"title":3012,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F10-docker\u002F05.Emby自有授权媒体库（一）","Emby 自有授权媒体库（一）",{"path":3014,"title":3015,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F10-docker\u002F06.Emby自有授权媒体库（二）","Emby 自有授权媒体库（二）",{"path":3017,"title":3018,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F10-docker\u002F07.Adguard-Home去广告","Adguard Home 去广告",{"path":3020,"title":3021,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F20-network\u002F01.新的篇章，软路由","新的篇章，软路由",{"path":3023,"title":3024,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F20-network\u002F02.如何玩公网，怎么远程访问（一）","如何玩公网，怎么远程访问（一）",{"path":3026,"title":3027,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F20-network\u002F03.如何玩公网，怎么远程访问（二）","如何玩公网，怎么远程访问（二）",{"path":3029,"title":3030,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F20-network\u002F04.如何玩公网，怎么远程访问（三）","如何玩公网，怎么远程访问（三）",{"path":3032,"title":3033,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F20-network\u002F05.免费域名与远程访问","免费域名与远程访问",{"path":3035,"title":3036,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F20-network\u002F06.没有公网如何远程访问","没有公网如何远程访问",{"path":3038,"title":3039,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F20-network\u002F07.爱快与OpenWRT双软路由MAC地址重复问题修正","爱快与 OpenWRT 双软路由MAC地址重复问题修正",{"path":3041,"title":3042,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F20-network\u002F08.OpenWRT扩容","OpenWRT 扩容",{"path":3044,"title":3045,"date":3000},"\u002Fblog\u002F10-技术专栏\u002F20-network\u002F09.OpenWRT旁路由一条龙教程","OpenWRT 旁路由一条龙教程",{"path":3047,"title":3048,"date":3000},"\u002Fblog\u002F20-生活碎片\u002F02.在裂缝中种满阳光","让灵魂带着光行走：在裂缝中种满太阳",{"path":3050,"title":3051,"date":3000},"\u002Fblog\u002F30-学习笔记\u002F01.Typora学习笔记","Typora学习笔记",{"path":3053,"title":3054,"date":3000},"\u002Fblog\u002F30-学习笔记\u002F02.Markdown-拓展","Markdown 拓展",{"path":3056,"title":3057,"date":3058},"\u002Fblog\u002F20-生活碎片\u002F01.拥抱生活中的光与热","拥抱生活中的光与热","2025-07-05",1791304407708]