欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

自己开发一个图床接口——基于 NodeJS.

程序员文章站 2022-06-30 22:59:11
...

前言

最近买了一堆服务器不知道要用来干什么…看到某乎上的回答,便准备搭建一个图床。但觉得这些现成的图床程序有些「花里胡哨」,于是便决定自己基于 NodeJS 开发一个图床接口自用。

为什么不用 OSS / COS?

阿里云 OSS, 腾讯云 COS 都属于对象存储。它的计费分为两部分:存储计费和流量计费。存储计费十分简单,并且都相应提供了存储包,十分划算。但是在流量计费上就有些复杂了,如果你的对象存储被人死刷流量,一夜破产都有可能。且我个人使用的阿里云 OSS 并没有频次控制功能,因此我选择购买一台服务器解决这个问题,因为它能通过一系列配置预防此类 CC 攻击。

如何实现?

我们可以将这个图床接口看作这些「简单」的动作。

客户端发送 POST 请求->反向代理(可选)->Express->反向代理(可选)->返回图床JSON数据。

而对于后端的 NodeJS,我们大概需要对传入的图片做这些处理。

  • 获取文件名的 MD5 值
  • 获取传入图片的后缀名
  • 将图片以文件名 “图片文件名MD5 + 传入图片后缀名” 的形式进行存储
  • 向客户端返回 JSON (包含 status 和图片链接)

知道了这些,我们就可以开始愉快的开发了。

开发

首先我们需要引入 express 框架,并创建一个应用。express 需要通过 npm 进行安装。

const express = require(‘express’);
const app = express();

之后在这基础上,创建一个 server 并监听 4000 端口。

var server = app.listen(4000, ‘127.0.0.1’, function(){
var host = server.address().address;
var port = server.address().port;
console.log(“Server running at http://%s:%s”, host, port);
})

之后,我们便可以开始解决 POST 文件的处理了。

首先,我们需要引入和配置这些中间件和模块,它们各自的作用已经写在注释了。

// 工具库 - lodash
const _ = require('lodash');
// assert - 测试是否为真值
const { ok } = require('assert');
// crypto - 用于获取文件名 MD5 值
const crypto = require('crypto');
// path - 用于获取文件拓展名
var path=require('path');

// 使用 express-fileupload 中间件
const fileUpload = require('express-fileupload');
app.use(fileUpload({
    createParentPath: true
}));

// 处理跨域问题 - cors 模块
const cors = require('cors');
app.use(cors());

// 解析 POST 数据
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

// 使用 morgan 中间件 - 输出请求详细信息
const morgan = require('morgan');
app.use(morgan('dev'));

接下来,便可以编写接收和处理数据的代码了。

app.post('/api/post', async (req, res) => {
    try {
        // 如果没有文件被上传,则返回以下 JSON 数据
        if(!req.files) {
            res.send({
                status: "No file uploaded",
                link: "undefined"
            })
        }
        else{
            let avatar = req.files.avatar; // 声明字段名为 avatar 的图片数据为 avatar 变量
            let md5 = crypto.createHash('md5').update(avatar.name).digest('hex'); // 取 avatar 文件名的 MD5 值
            avatar.mv('./uploads/' + md5 + path.extname(avatar.name)); // 存储(移动)图片到 uploads 文件夹,文件名为 avatar 文件名 MD5 + 文件拓展名
            // 发送以下 JSON 数据
            res.send({
                status: "ok",
                link: "https://example.com/uploads/" + md5 + path.extname(avatar.name)
            });
        }
    }
    // 如果上传出现错误,则返回 HTTP 500.
    catch (err) {
        res.status(500).send(err);
    }
})

最后,你可以尝试运行 app.js 然后使用 Postman 来测试它。

node app.js

自己开发一个图床接口——基于 NodeJS.自己开发一个图床接口——基于 NodeJS.

进阶操作 (外网服务配置 + 持久化)

如果要在公网上进行使用,我们或许需要配置 Nginx 反向代理到 express. 当然,你也可以直接将 Express 暴露在公网上。

以下是我的反向代理配置,从宝塔面板抄来的。

location  ~* \.(php|jsp|cgi|asp|aspx)$
{
proxy_pass http://localhost:4000;
proxy_set_header Host localhost;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
}
location /api/post
{
proxy_pass http://localhost:4000;
proxy_set_header Host localhost;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
#Set Nginx Cache
add_header Cache-Control no-cache;
expires 12h;
}

同时为了方便,我将图片存储在了站点根目录的 uploads 文件夹中。当然,你也需要更改 app.js 中的相应代码。

avatar.mv(‘/usr/local/openresty/nginx/html/uploads/’ + md5 + path.extname(avatar.name));

为了持久化运行,你也可以使用 forever 守护此进程。

npm install -g forever
forever start app.js

使用(uPic)

既然都开发好了…我们怎么能不对其进行应用呢(

这里我使用了 uPic 这个开源工具,你可以查看这篇文章进行了解:「uPic:支持自定义,一款免费而强大的Mac图床客户端

你可以参考下图,对你的 uPic 进行配置。
自己开发一个图床接口——基于 NodeJS.