【node】使用express+gitee搭建图床,并解决防盗链问题

首先创建一个gitee的项目,详细步骤我就不一一说明

注解:大家记得将这个项目开源,还有记得获取自己的私钥,私钥操作如下:

node依赖下载:

"axios": "cors": "express": "multer": "nodemon":

app.js代码:

javascript 复制代码
const express = require('express');
const multer = require('multer');
const axios = require('axios');
const cors = require('cors');

const app = express();
app.use(cors());
const port = 3000;

// 设置 Multer 中间件来处理文件上传
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });

// 处理静态文件
app.use(express.static('public'));

// 显示图床上的所有图片
app.get('/', async (req, res) => {
  try {
    const response = await axios.get('https://gitee.com/api/v5/repos/zsd12138/drawing-bed/contents/image?access_token=xxxxxxxxxx');
    const images = response.data.map(item => item.download_url);
    res.send(`
      <div style="display: flex;">
        ${images.map(image =>
      `<div style="display: flex;
          flex-direction: column;
          align-items: center;"><img src="${image}" style="height: 200px;margin-right: 20px;"> <span  style="cursor: pointer;">点击图片删除</span></div>`
    ).join('')}
      </div>
    `);
  } catch (error) {
    console.error(error);
    res.status(500).send('无法获取图片列表');
  }
});

// 上传图片到图床
app.post('/upload', upload.single('image'), async (req, res) => {
  try {
    const { buffer, originalname } = req.file;
    const encodedFile = buffer.toString('base64');
    const response = await axios.post('https://gitee.com/api/v5/repos/zsd12138/drawing-bed/contents/image/' + originalname, {
      access_token: "xxxxxxxxxx",
      branch: 'master',
      content: encodedFile,
      message: `上传图片 ${originalname}`,
    });
    res.status(200).send(response.data);
  } catch (error) {
    // console.error(error);
    res.status(500).send('无法上传图片');
  }
});

// 删除图床上的图片
app.get('/delete/:filename', async (req, res) => {
  const filename = req.params.filename;
  try {
    // 获取sha
    const shaDate = await axios.get('https://gitee.com/api/v5/repos/zsd12138/drawing-bed/contents/image/' + filename + '?access_token=xxxxxxxxxxx');
    // console.log(shaDate.data.sha)
    // 删除操作
    const response = await axios.delete('https://gitee.com/api/v5/repos/zsd12138/drawing-bed/contents/image/' + filename, {
      params: {
        access_token: "xxxxxxxxxxxxx",
        branch: 'master',
        message: `删除图片 ${filename}`,
        sha: shaDate.data.sha
      },
    });
    res.status(200).send(`已删除${filename}`);
  } catch (error) {
    console.error(error.data);
    res.status(500).send(`无法删除图片 ${filename}`);
  }
});

// 启动服务器
app.listen(port, () => {
  console.log(`服务器正在运行,访问 http://localhost:${port}`);
});

access_token替换成自己的私人令牌

index.html

html 复制代码
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>图床</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>

<body>
    <h2>上传图片</h2>
    <form id="uploadForm">
        <input type="file" id="fileInput">
        <button type="submit">上传图片</button>
    </form>

    <h2>所有图片</h2>
    <div id="images"></div>

    <script>
        $(function () {
            // 删除图片
            $('#images').on('click', 'img', function () {
                const imageUrl = $(this).attr('src');
                const filename = imageUrl.substring(imageUrl.lastIndexOf('/') + 1);
                if (confirm(`确定删除 "${filename}"?`)) {
                    $.ajax({
                        url: 'http://172.21.2.52:3000/delete/' + filename,
                        type: 'get',
                        success: () => {
                            // $(this) 表示当前被选中的元素,.remove() 用于从 DOM 中移除元素。
                            // $(this).remove();
                            getIamge()
                        },
                        error: () => {
                            alert('Delete failed.');
                        }
                    });
                }
            });
        })
        var getIamge = function () {
            // 获取图床上的所有图片
            $.ajax({
                url: 'http://172.21.2.52:3000/',
                method: 'GET',
                success: function (html) {
                    $('#images').html(html);
                },
                error: function () {
                    console.error('无法获取图片列表');
                }
            });
        }
        getIamge()
        // 上传图片到图床
        $('#uploadForm').submit(function (event) {
            event.preventDefault(); // 阻止表单的默认提交行为

            const formData = new FormData();
            formData.append('image', $('#fileInput')[0].files[0]);
            console.log($('#fileInput')[0].files[0])
            $.ajax({
                url: 'http://172.21.2.52:3000/upload',
                type: 'POST',
                data: formData,
                processData: false,
                contentType: false,
                success: function (result) {
                    getIamge()
                    console.log(result);
                },
                error: function (error) {
                    console.error(error);
                }
            });
        })

    </script>
</body>

</html>

运行效果:全部都302 重定向了,这就是做了防盗链,下面来讲讲防盗链

防盗链

要实现防盗链,就需要知道图片的请求是从哪里发出的。可以实现这一功能的有请求头中的originrefererorigin只有在XHR请求中才会带上,所以图片资源只能借助referer

通过判断请求的referer,如果请求来源不是本站就返回302

一个完整的流程:

  • 首先请求正常的图片,但是没有返回200,而是302重定向,其中响应头中的location就是要重定向去向的地址;
  • 接着浏览器会自动请求这个location,并用这个返回结果代替第一次请求的返回内容

如何破解防盗链

想让gitee不知道我在盗用,就不能让他发现请求的来源是第三方,只要把referer藏起来就好

代码实现:

html 复制代码
//增加到html的头部
<meta name="referrer" content="no-referrer" />

注解:
<meta name="referrer" content="no-referrer" /> 指定了 "no-referrer" 的内容,意味着浏览器在发送请求时不会包含任何引用来源信息。换句话说,当用户从当前网页跳转到其他页面时,新页面接收到的请求中将不包含这个跳转前的页面地址

最后效果图

增加meta头部配置后

附上gitee请求文档:

Gitee API 文档

相关推荐
编程乐学12 小时前
基于Android Studio 蜜雪冰城(奶茶饮品点餐)—原创
android·gitee·android studio·大作业·安卓课设·奶茶点餐
茜茜西西CeCe19 小时前
移动技术开发:简单计算器界面
java·gitee·安卓·android-studio·移动技术开发·原生安卓开发
一个很帅的帅哥1 天前
实现浏览器的下拉加载功能(类似知乎)
开发语言·javascript·mysql·mongodb·node.js·vue·express
黎相思1 天前
操作系统迁移(CentOs -> Ubuntu)
linux·ubuntu·gitee·centos
茜茜西西CeCe1 天前
移动技术开发:登录注册界面
java·gitee·gradle·android studio·安卓·移动技术开发·原生安卓开发
QQ13049796942 天前
Vue+nodejs+express旅游景区门票预订网站的设计与实现 8caai前后端分离
vue.js·express·旅游
qq22951165022 天前
python毕业设计基于django+vue医院社区医疗挂号预约综合管理系统7918h-pycharm-flask
前端·vue.js·express
冬田里的一把火32 天前
[Android][Reboot/Shutdown] 重启/关机 分析
android·gitee
毅凉3 天前
git笔记
gitee·github·gitcode
爱吃香蕉的阿豪3 天前
828华为云征文|Flexus X实例Docker+Jenkins+gitee实现CI/CD自动化部署-解放你的双手~
ci/cd·docker·gitee·华为云·jenkins