创作背景
众所周知,本网站导航栏中有一「能效」栏目。该栏目中的三个页面,都是旧网站中没有的,是我在新网站创立之初灵机一动想到的。为了更明显地区分它们与主站,我特意选择了不同的背景图源 API,这在「自述江湖」中有提到。
但是,我在寻找“二次元风景壁纸 API”时发现这些 API 大部分都难以令我满意,费尽周折才选出这一个,但是图库比较小。恰好我手里有一些图片,于是就萌生了自制 API 的想法。
项目可以部署在 netlify functions 上。这款服务是免费提供的——至少是够用的。
当我询问 netlify AI chatbot 时,它这样回答我:
根据提供的知识来源,Netlify Functions 的免费额度如下:
- 每月 125,000 次函数调用
- 每月 300 分钟的运行时间
这些信息来自Netlify的免费计划介绍博客文章。
此外,值得注意的是:
- 免费计划有使用限制。当达到限制时,您会收到电子邮件通知(在使用量达到 50%、75%、90% 和 100% 时)。
- 如果达到构建限制,您的网站仍然可以访问,但新的构建将被禁用。
- 对于其他计量功能,如果达到 100% 的限制,新的构建将被禁用,并且您账户下的所有网站都将被暂停。
- 要恢复服务,您需要添加付款方式并升级到付费计划。
这些额外信息来自Netlify的计费FAQ文档。
如果您需要更高的限额或有其他具体需求,建议查看Netlify的付费计划或联系他们的销售团队。
所以,对于中小型网站,比如本网站,是完全够用的。如果你不放心,可以手搓负载均衡。
然而,本网站新栏目现在使用的是另外一种形式的 PicFlare。不过本质上是一样的,问题不大。
另外,有些文章没有封面,为了优化 UI,它们的默认封面很可能是 PicFlare 提供的喔!~
效果展示
我制作了一个项目,托管在 Github 上。即:https://github.com/pandaoxi/picflare
DEMO 见:https://picflare.netlify.app/。
核心 API 接口:https://picflare.netlify.app/api/picflare。
当然,如果你乐意,你当然可以把 API 利用在 Markdown 中。
1
| ![图:Markdown 中的 PicFlare API](https://picflare.netlify.app/api/picflare)
|
原理
具体的操作方法见仓库中的使用说明。我主要说说原理。
结构
1 2 3 4 5 6 7 8 9 10 11 12 13
| . │ netlify.toml │ README.md │ ├─functions │ picflare.js │ └─public │ index.html │ └─images wallhaven-yjr3lk.webp wallhaven-z8jvqw.webp
|
JS 实现
我们要从 JS 中获取图库文件夹,需要协调函数与静态资源的位置关系。这需要设置 netlify.toml
。
1 2 3 4 5 6 7 8 9 10 11 12
| [build] publish = "public"
[functions] directory = "functions" included_files = ["public/**"]
[[redirects]] from = "/api/*" to = "/.netlify/functions/:splat" status = 200 force = true
|
然后可以通过 JS 访问文件夹,随机获取一张图片并返回。这些操作都可以在一个 picflare.js
内完成。具体地,JS 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
const fs = require("fs"); const path = require("path");
exports.handler = async (event) => { const imagesDir = path.resolve(__dirname, "..", "public", "images"); const imageFiles = fs.readdirSync(imagesDir); const randomImageFile = imageFiles[Math.floor(Math.random() * imageFiles.length)]; const imagePath = path.join(imagesDir, randomImageFile); const imageData = fs.readFileSync(imagePath); const headers = { "Content-Type": "image/webp", }; return { statusCode: 200, headers, isBase64Encoded: true, body: imageData.toString("base64"), }; };
|
本网站为了减轻负担,每天对应一张图片。JS 可以这样写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| const fs = require("fs"); const path = require("path");
exports.handler = async (event) => { const imagesDir = path.resolve(__dirname, "..", "public", "images"); const imageFiles = fs.readdirSync(imagesDir); const today = new Date(); const dayOfYear = getDayOfYear(today); const imageIndex = (dayOfYear - 1) % imageFiles.length; const randomImageFile = imageFiles[imageIndex]; const imagePath = path.join(imagesDir, randomImageFile); const imageData = fs.readFileSync(imagePath); const headers = { "Content-Type": "image/webp", }; return { statusCode: 200, headers, isBase64Encoded: true, body: imageData.toString("base64"), }; };
function getDayOfYear(date) { const start = new Date(date.getFullYear(), 0, 0); const diff = date - start; const oneDay = 1000 * 60 * 60 * 24; return Math.ceil(diff / oneDay); }
|
因此,PicFlare 并不是一个复杂的项目。欢迎贡献!