告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案

admin 2025年4月14日09:00:17评论3 views字数 6036阅读20分7秒阅读模式
在自媒体创作、技术博客或项目开发中,图片托管始终是个绕不开的痛点。传统图床要么收费昂贵,要么存在速度限制,要么存在隐私安全隐患,甚至面临突然关停的风险。今天要分享的方案完美结合了GitHub的免费存储与Cloudflare的全球加速网络,只需不到20分钟即可搭建一个:

✓ 完全免费的图片托管服务

✓ 享受全球CDN极速访问

✓ 支持自动缓存优化

✓ 数据完全自主可控

无需服务器、无需复杂配置,跟着本文一步步操作,让你的图片加载速度提升300%,彻底告别第三方图床的种种限制!

如果有小伙伴不想自己搭建,可以在后台私信或者✈上联系我代搭建,不过得收点技术费。

前期需要安装的软件:

PicGo:PicGo 是一款开源的图床工具,主要用于将本地图片上传到各大图床(如 GitHub、阿里云 OSS、腾讯云 COS、七牛云、SM.MS 等),并自动复制图片链接,方便在博客、论坛或文档中使用。

https://github.com/Molunerfinn/PicGo/releases/tag/v2.3.1
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案

Windows用户下载我标记的安装程序即可。

前期需要准备的账号:
1、GitHub
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
2、Cloudflare
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
✅任务一:GitHub创建仓库
在GitHub首页右上角有个+,创建一个存储库。
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
设置存储名称,输入自己的用户名或者容易记住的即可,建议加一个-img,标记出这是一个图床即可,描述自定义,可以不填,然后把仓库设置成私有的,其他的默认即可,然后点击“创建存储库”。
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
点击右上角个人头像,显示侧边栏,点击设置。
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
在设置页面左侧的侧边栏滑到底部,找到"Developer settings"
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
点击“个人访问令牌”。
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
点击生成新令牌按钮,选择第二项。
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
笔记(Note)输入框这里输入名称,自定义即可,不要输入中文。到期时间选择最后一项,无有效期,选择范围这里点击reop,把这个选项卡中的选项都选择,其他的保持默认,然后滑到底部,点击生成令牌(Generate token)。
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
这里生成的令牌密钥一定要保存好,页面关闭之后这里就没有了。
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
✅任务二:PicGo配置
打开PicGo,在图床设置中找到GitHub选项,根据下方图片配置即可,Token就是在GitHub复制的令牌密钥。域名就填写你购买的域名,不过还需要做一些设置,继续往下看,然后点击确定,再点击设为默认图库。
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
点击上传区测试一下能否上传成功。上传成功之后,刷新以下GitHub图床仓库,你会发现仓库中显示出来了你上传的图片。
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
✅任务三:Cloudflare配置
打开Cloudflare,在左侧侧边栏找到“Workers和Pages”,点击创建一个Workers,点击这里的Hello World。
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
输入你的项目名称
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
部署成功之后,点击继续处理项目
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
点击右上方的代码编辑图标,进行编辑代码
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
清空里面的代码,复制以下代码,编辑第6行和第10行:
// Website you intended to retrieve for users.const upstream"raw.githubusercontent.com";// Custom pathname for the upstream website.// (1) 填写代理的路径,格式为 /<用户>/<仓库名>/<分支>const upstream_path = "/用户名/仓库名/master";// github personal access token.// (2) 填写github令牌const github_token = "";// Website you intended to retrieve for users using mobile devices.const upstream_mobile = upstream;// Countries and regions where you wish to suspend your service.const blocked_region = [];// IP addresses which you wish to block from using your service.const blocked_ip_address = ["0.0.0.0""127.0.0.1"];// Whether to use HTTPS protocol for upstream address.const https = true;// Whether to disable cache.const disable_cache = false;// Replace texts.const replace_dict = {  $upstream: "$custom_domain",};addEventListener("fetch", (event) => {  event.respondWith(fetchAndApply(event.request));});async function fetchAndApply(request) {  const region = request.headers.get("cf-ipcountry")?.toUpperCase();  const ip_address = request.headers.get("cf-connecting-ip");  const user_agent = request.headers.get("user-agent");  let response = null;  let url = new URL(request.url);  let url_hostname = url.hostname;  if (https == true) {    url.protocol = "https:";  } else {    url.protocol = "http:";  }  if (await device_status(user_agent)) {    var upstream_domain = upstream;  } else {    var upstream_domain = upstream_mobile;  }  url.host = upstream_domain;  if (url.pathname == "/") {    url.pathname = upstream_path;  } else {    url.pathname = upstream_path + url.pathname;  }  if (blocked_region.includes(region)) {    response = new Response(      "Access denied: WorkersProxy is not available in your region yet.",      {        status: 403,      }    );  } else if (blocked_ip_address.includes(ip_address)) {    response = new Response(      "Access denied: Your IP address is blocked by WorkersProxy.",      {        status: 403,      }    );  } else {    let method = request.method;    let request_headers = request.headers;    let new_request_headers = new Headers(request_headers);    new_request_headers.set("Host", upstream_domain);    new_request_headers.set("Referer", url.protocol + "//" + url_hostname);    new_request_headers.set("Authorization""token " + github_token);    let original_response = await fetch(url.href, {      method: method,      headers: new_request_headers,      body: request.body,    });    connection_upgrade = new_request_headers.get("Upgrade");    if (connection_upgrade && connection_upgrade.toLowerCase() == "websocket") {      return original_response;    }    let original_response_clone = original_response.clone();    let original_text = null;    let response_headers = original_response.headers;    let new_response_headers = new Headers(response_headers);    let status = original_response.status;    if (disable_cache) {      new_response_headers.set("Cache-Control""no-store");    } else {      new_response_headers.set("Cache-Control""max-age=43200000");    }    new_response_headers.set("access-control-allow-origin""*");    new_response_headers.set("access-control-allow-credentials"true);    new_response_headers.delete("content-security-policy");    new_response_headers.delete("content-security-policy-report-only");    new_response_headers.delete("clear-site-data");    if (new_response_headers.get("x-pjax-url")) {      new_response_headers.set(        "x-pjax-url",        response_headers          .get("x-pjax-url")          .replace("//" + upstream_domain, "//" + url_hostname)      );    }    const content_type = new_response_headers.get("content-type");    if (      content_type != null &&      content_type.includes("text/html") &&      content_type.includes("UTF-8")    ) {      original_text = await replace_response_text(        original_response_clone,        upstream_domain,        url_hostname      );    } else {      original_text = original_response_clone.body;    }    response = new Response(original_text, {      status,      headers: new_response_headers,    });  }  return response;}async function replace_response_text(response, upstream_domain, host_name) {  let text = await response.text();  var i, j;  for (i in replace_dict) {    j = replace_dict[i];    if (i == "$upstream") {      i = upstream_domain;    } else if (i == "$custom_domain") {      i = host_name;    }    if (j == "$upstream") {      j = upstream_domain;    } else if (j == "$custom_domain") {      j = host_name;    }    let re = new RegExp(i, "g");    text = text.replace(re, j);  }  return text;}async function device_status(user_agent_info) {  var agents = [    "Android",    "iPhone",    "SymbianOS",    "Windows Phone",    "iPad",    "iPod",  ];  var flag = true;  for (var v = 0; v < agents.length; v++) {    if (user_agent_info.indexOf(agents[v]) > 0) {      flag = false;      break;    }  }  return flag;}
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
修改完成之后,点击右上角的部署按钮,然后点击左上角的仓库名,返回上一页。
接着配置域,点击设置,点击域和路由,点击右上方的添加,选择自定义路由,输入一个格式为:
image.你的域名
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
把你这里自定义的域名填写进你的PicGo的GitHub处的自定义域名,记得前边加https://,参照我以下格式:
https://图床域名
在图片上传区,链接格式要选择URL,然后再次上传一张图片,上传成功之后点击左侧相册选项,原本显示不出来的图片,现在通过Cloudflare加速能显示出来了,这就证明成功了。
告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案
然后你在浏览器地址栏输入:
https://图床域名/图片名称.jpg
访问到你上传的图片,那么恭喜你,成功了。
不过个人私有仓库的容量只有1个G,对于个人博客使用而言,还是够用的,如果超出容量,可以再创建一个仓库,按照相同的步骤操作即可。
本篇文章到此结束,写作不易,多多支持。
三连加关注,追文不迷路。

原文始发于微信公众号(W不懂安全):告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年4月14日09:00:17
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   告别付费图床:基于GitHub与Cloudflare的图床搭建专属存储方案http://cn-sec.com/archives/3952111.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息