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

news2024/11/24 16:55:44

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

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

node依赖下载:

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

app.js代码:

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

<!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的头部
<meta name="referrer" content="no-referrer" />

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

最后效果图

增加meta头部配置后 

附上gitee请求文档:

Gitee API 文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/784052.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FPGA设计时序分析一、时序路径

目录 一、前言 二、时序路径 2.1 时序路径构成 2.2 时序路径分类 2.3 数据捕获 2.4 Fast corner/Slow corner 2.5 Vivado时序报告 三、参考资料 一、前言 时序路径字面容易简单地理解为时钟路径&#xff0c;事实时钟存在的意义是为了数据的处理、传输&#xff0c;因此严…

记一次简单的MySql注入试验

试验环境&#xff1a; 1.已经搭建好的php服务器&#xff0c;并可以通过访问到localhost/index.php&#xff1b; 2.已经安装好数据库&#xff0c;并创建表test&#xff0c;表内有name、age等字段&#xff0c;并随便创建几个假数据用于测试&#xff1b;如图&#xff1a; 开始测…

docker 禅道 远程链接 MySQL

主要的坑在下边 红色字体&#xff1a;认真看 第一种方法 搜索镜像 docker search zentao 拉取镜像 docker pull easysoft/zentao:latest 启动容器 –name [容器名] 设置容器名称 -p [主机端口]:80 绑定端口 -v /home/zentao/zentaopms:/www/zentaopms 挂载数据目录 /h…

idea中Easy Code模版配置

首先找到模版位置 找到使用的模版&#xff0c;我用的是MybatisPlus-H,这是我新建的一个模版 controller.java.vm模版 ##导入宏定义 $!{define.vm}##设置表后缀&#xff08;宏定义&#xff09; #setTableSuffix("Controller")##保存文件&#xff08;宏定义&#xff…

PHP8知识详解:PHP8开发工具VS Code的安装

作为PHP8的开发工具有很多&#xff0c;具有IDE功能的有phpstorm、Visual Studio Code、Sublime Text、NetBeans、Eclipse、Codelobster、PHP Designer等&#xff0c;当然还有很多轻量的工具&#xff0c;比如Notepad、Editplus等。本文给你介绍的是万能编辑器Visual Studio Code…

Python基于PyTorch实现循环神经网络回归模型(LSTM回归算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 LSTM网络是目前更加通用的循环神经网络结构&#xff0c;全称为Long Short-Term Memory&#xff0c;翻…

计算机视觉(二)图像特征提取

文章目录 颜色特征量化颜色直方图适用颜色空间&#xff1a;RGB、HSV等颜色空间操作 几何特征边缘 Edge边缘定义边缘提取 基于关键点的特征描述子引入几何特征&#xff1a;关键点几何特征&#xff1a;Harris角点FAST角点检测几何特征&#xff1a;斑点局部特征&#xff1a;SIFT预…

GPT-4 模型详细教程

GPT-4&#xff08;Generative Pretrained Transformer 4&#xff09;是 OpenAI 的最新语言生成模型&#xff0c;其在各类文本生成任务中表现优秀&#xff0c;深受开发者和研究者喜爱。这篇教程将帮助你理解 GPT-4 的基本概念&#xff0c;并向你展示如何使用它来生成文本。 什么…

前端vue入门(纯代码)35_导航守卫

星光不问赶路人&#xff0c;时光不负有心人 【33.Vue Router--导航守卫】 导航守卫 正如其名&#xff0c;vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中&#xff1a;全局的, 单个路由独享的, 或者组件级的。 记住参数或查…

uniapp JS文件里面调用自定义组件(不用每个页面在template中加组件标签)

前言 工具&#xff1a;uniapp 开发端&#xff1a;微信小程序 其他&#xff1a;uview 2.0 场景&#xff1a;路由器里面&#xff0c;统一验证是否已登录&#xff0c;如果没登录&#xff0c;则直接弹出登录弹窗出来&#xff0c;不管哪个页面都如此。 效果如下&#xff1a; 直接上…

【笔试强训选择题】Day29.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;&#xff…

rsync—远程同步

目录 一&#xff1a;rsync概述 1.1rsync简介 1.2rsync同步方式 二&#xff1a;rsync特性 三&#xff1a;rsync同步源 四&#xff1a;rsync与cp、scp对比 五&#xff1a;常用rsync命令 六&#xff1a;rsync本地复制实例 七&#xff1a;配置源的俩种表示方法 八&#x…

[NLP]Huggingface模型/数据文件下载方法

问题描述 作为一名自然语言处理算法人员&#xff0c;hugging face开源的transformers包在日常的使用十分频繁。在使用过程中&#xff0c;每次使用新模型的时候都需要进行下载。如果训练用的服务器有网&#xff0c;那么可以通过调用from_pretrained方法直接下载模型。但是就本人…

安全DNS,状态码,编码笔记整理

一 DNS DNS&#xff08;Domain Name System&#xff09;是互联网中用于将域名转换为IP地址的系统。 DNS的主要功能包括以下几个方面&#xff1a; 域名解析&#xff1a;DNS最主要的功能是将用户输入的域名解析为对应的IP地址。当用户在浏览器中输入一个域名时&#xff0c;操作…

工程安全监测无线振弦采集仪在建筑物中的应用

工程安全监测无线振弦采集仪在建筑物中的应用 工程安全监测无线振弦采集仪是一种用于建筑物结构安全监测的设备&#xff0c;它采用了无线传输技术&#xff0c;具有实时性强、数据精度高等优点&#xff0c;被广泛应用于建筑物结构的实时监测和预警。下面将从设备的特点、应用场…

力扣热门100题之接雨水【困难】

题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1,3…

如何使用GPT作为SQL查询引擎的自然语言

​生成的AI输出并不总是可靠的&#xff0c;但是下面我会讲述如何改进你的代码和查询的方法&#xff0c;以及防止发送敏感数据的方法。与大多数生成式AI一样&#xff0c;OpenAI的API的结果仍然不完美&#xff0c;这意味着我们不能完全信任它们。幸运的是&#xff0c;现在我们可以…

Packet Tracer – 配置动态 NAT

Packet Tracer – 配置动态 NAT 拓扑图 目标 第 1 部分&#xff1a;配置动态 NAT 第 2 部分&#xff1a;验证 NAT 实施 第 1 部分&#xff1a; 配置动态 NAT 步骤 1&#xff1a; 配置允许的流量。 在 R2 上&#xff0c;为 ACL 1 配置一个语句以允许属于 172.16.0.…

【JVM】浅看JVM的运行流程和垃圾回收

1.JVM是什么 JVM&#xff08; Java Virtual Machine&#xff09;就是Java虚拟机。 Java的程序都运行在JVM中。 2.JVM的运行流程 JVM的执行流程&#xff1a; 程序在执行之前先要把java代码转换成字节码&#xff08;class文件&#xff09;&#xff0c;JVM 首先需要把字节码通过…