当前位置: 首页 > news >正文

基于 STM32 的 NAS私有云盘搭建:集成LwIP 协议、HTTP/HTTPS、WEB前端技术栈(代码示例)

项目概述

在本项目中,我们将搭建一个基于 STM32 的 NAS(网络附加存储)私盘,通过网络访问存储在外部 SATA 硬盘上的文件。该项目将使用 STM32 开发板、外接 SATA 硬盘、LwIP 协议栈以及 FATFS 文件系统来实现文件的上传、下载和管理,用户可以通过简单的 Web 界面进行操作。

系统设计

硬件设计

  1. STM32 开发板

    • 选择 STM32F407 或 STM32F746 开发板,具备足够的 RAM 和闪存以支持 NAS 功能。
  2. 存储介质

    • 使用外接 SATA 硬盘,通过 SATA 转 USB 适配器连接到 STM32。
  3. 网络接口

    • 选择以太网模块(如 W5500)或 Wi-Fi 模块(如 ESP8266)以实现网络连接。
  4. 电源管理

    • 确保使用的电源适配器能够满足 STM32 开发板和外接硬盘的功耗需求。

软件设计

  1. 开发环境

    • 使用 STM32CubeIDE 或 Keil MDK 作为开发工具。
  2. 固件库

    • 使用 STM32 HAL 库进行硬件抽象和操作。
  3. 文件系统

    • 使用 FATFS 库来管理存储设备上的文件系统,支持文件的读写、删除等操作。
  4. 网络协议

    • 使用 LwIP 协议栈处理 TCP/IP 网络通信。
    • 实现 HTTP/HTTPS 协议以支持 Web 服务器功能,支持文件的上传和下载。

配置环境

1. 安装 STM32CubeIDE

  • 下载并安装 STM32CubeIDE。
  • 按照安装向导完成安装过程。

2. 创建新项目

  1. 打开 STM32CubeIDE,选择 File -> New -> STM32 Project
  2. 在 Board Selector 中选择您的 STM32 开发板(如 STM32F407 或 STM32F746)。
  3. 配置项目名称和存储路径,点击 Finish

3. 启用所需的中间件

  1. 在左侧的 Project Explorer 中,右键单击项目名称,选择 Properties
  2. 选择 C/C++ Build -> Settings -> Tool Settings,确保选择了适当的编译工具链。
  3. 右键单击项目,选择 Manage Embedded Software Packages,然后选择 FATFS 和 LwIP 进行添加和配置。

4. 配置网络接口

  • 根据所选的网络模块(以太网或 Wi-Fi),在 Pinout & Configuration 视图中配置相应的引脚和设置。
  • 对于以太网模块,请确保启用以太网外设并配置 MAC 地址等参数。

5. 配置外部存储

  1. 将 SATA 硬盘连接到 STM32 开发板的 USB 接口。
  2. 在 FATFS 中配置相关参数,以确保可以识别和访问外部存储。

6. 添加库文件

  • 导入必要的库文件(如 LwIP 和 FATFS)到项目中,并确保在 main.c 或其他相应文件中包含头文件。

STM32代码实现

以下是项目的主要代码实现部分,包括网络初始化、文件操作和 HTTP 服务器的实现。

1. 初始化和网络配置

#include "lwip/init.h"
#include "lwip/netif.h"
#include "lwip/tcpip.h"
#include "ethernetif.h"void init_network(void) {lwip_init(); // 初始化 LwIPstruct netif my_netif;ip_addr_t ipaddr, netmask, gw;// 设置网关和子网IP4_ADDR(&gw, 192, 168, 1, 1); // 网关IP4_ADDR(&ipaddr, 192, 168, 1, 100); // 设备 IPIP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码netif_add(&my_netif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, tcpip_input);netif_set_default(&my_netif); // 设置为默认网络接口netif_set_up(&my_netif); // 启动网络接口
}

说明

  • lwip_init() 初始化 LwIP(轻量级 IP 协议栈)。
  • 使用 netif_add() 添加网络接口,并配置 IP、网关和子网掩码。
  • netif_set_up() 启动网络接口,使其可以进行通信。

2. 文件系统操作

#include "ff.h" // FATFS 头文件void create_file(void) {FATFS fs;       // 文件系统对象FIL fil;        // 文件对象FRESULT res;    // 文件操作结果char buffer[] = "Hello, STM32 NAS!";// 挂载文件系统res = f_mount(&fs, "", 1); if (res == FR_OK) {// 创建文件并写入数据res = f_open(&fil, "test.txt", FA_WRITE | FA_CREATE_ALWAYS); if (res == FR_OK) {f_write(&fil, buffer, sizeof(buffer), NULL); // 写入数据f_close(&fil); // 关闭文件}}
}

说明

  • FATFS 是文件系统的结构体,FIL 是文件对象。
  • 首先调用 f_mount() 挂载文件系统,这样就可以对存储设备进行操作。
  • 使用 f_open() 创建或打开文件,并使用 f_write() 写入数据。
  • 操作完成后,调用 f_close() 关闭文件,以释放资源。

3. HTTP 服务器实现

#include "httpd.h" // HTTP 服务器头文件void start_http_server(void) {httpd_init(); // 初始化 HTTP 服务器
}// HTTP 请求处理示例
static void handle_get_request(struct httpd_state *hs) {const char *response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nHello from STM32 NAS!";httpd_send(hs, response, strlen(response)); // 发送响应
}

说明

  • httpd_init() 初始化 HTTP 服务器,准备接受请求。
  • 处理 GET 请求的示例函数 handle_get_request() 发送一个简单的文本响应。

4. 主函数

int main(void) {// 初始化系统HAL_Init();SystemClock_Config(); // 配置系统时钟MX_GPIO_Init(); // 初始化 GPIOMX_SPI_Init(); // 初始化 SPI(用于以太网模块)MX_USB_OTG_FS_PCD_Init(); // 初始化 USB OTG(用于 SATA 硬盘)init_network(); // 初始化网络create_file(); // 创建文件start_http_server(); // 启动 HTTP 服务器while (1) {// 处理网络事件syscheck_timeouts();}
}

说明

  • HAL_Init() 初始化硬件抽象层,设置基本的硬件配置。
  • SystemClock_Config() 配置系统时钟,以保证系统的正常运行。
  • 调用 init_network() 初始化网络,create_file() 创建文件,start_http_server() 启动 HTTP 服务器。
  • 在 while (1) 循环中,不断处理网络事件,保持系统运行。

Web 前端界面交互搭建

1. 项目结构

首先,您需要创建一个简单的项目结构,用于存放前端文件。假设我们将所有的前端文件放在 STM32 的文件系统中的 /www 目录下,项目结构如下:

/www├── index.html├── style.css└── script.js

2. HTML 页面(index.html)

下面是一个简单的 HTML 页面,提供文件上传和下载的功能。

<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>STM32 NAS 私盘</title><link rel="stylesheet" href="style.css">
</head>
<body><div class="container"><h1>STM32 NAS 私盘</h1><div class="upload-section"><h2>上传文件</h2><input type="file" id="fileInput"><button id="uploadButton">上传</button></div><div class="file-list"><h2>文件列表</h2><ul id="fileList"></ul></div></div><script src="script.js"></script>
</body>
</html>

3. CSS 样式(style.css)

下面是简单的 CSS 样式,用于美化前端界面。

body {font-family: Arial, sans-serif;background-color: #f4f4f4;margin: 0;padding: 20px;
}.container {max-width: 600px;margin: 0 auto;background: #fff;padding: 20px;border-radius: 5px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}h1 {text-align: center;
}.upload-section, .file-list {margin-bottom: 30px;
}button {padding: 10px 15px;background-color: #28a745;color: white;border: none;border-radius: 5px;cursor: pointer;
}button:hover {background-color: #218838;
}

4. JavaScript 代码(script.js)

我们将使用 AJAX 来与 STM32 后端进行交互,实现文件上传和获取文件列表的功能。

document.getElementById('uploadButton').onclick = function() {const fileInput = document.getElementById('fileInput');const file = fileInput.files[0];if (!file) {alert('请选择一个文件!');return;}const formData = new FormData();formData.append('file', file);fetch('/upload', { // 发送文件到后端method: 'POST',body: formData}).then(response => response.text()).then(data => {alert(data);loadFileList(); // 上传成功后更新文件列表}).catch(error => console.error('Error:', error));
};function loadFileList() {fetch('/files') // 请求文件列表.then(response => response.json()).then(files => {const fileList = document.getElementById('fileList');fileList.innerHTML = ''; // 清空文件列表files.forEach(file => {const li = document.createElement('li');li.textContent = file;fileList.appendChild(li);});}).catch(error => console.error('Error:', error));
}// 页面加载时获取文件列表
window.onload = loadFileList;

5. 后端实现

为了使前端能够与后端进行交互,我们需要在 STM32 的 HTTP 服务器中处理文件上传和文件列表请求。

1. 处理文件上传的代码

#include "httpd.h" // HTTP 服务器头文件
#include "ff.h" // FATFS 头文件// 处理文件上传请求
static void handle_file_upload(struct httpd_state *hs) {char buf[512];FIL fil;FRESULT res;char *filename = "uploaded_file.txt"; // 上传的文件名// 读取 HTTP 请求体int bytes_read = httpd_read_request_body(hs, buf, sizeof(buf));if (bytes_read > 0) {// 创建文件并写入数据res = f_open(&fil, filename, FA_WRITE | FA_CREATE_ALWAYS);if (res == FR_OK) {f_write(&fil, buf, bytes_read, NULL); // 写入文件f_close(&fil); // 关闭文件httpd_send_response(hs, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nFile uploaded successfully!"); // 响应成功} else {httpd_send_response(hs, "HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain\r\n\r\nFailed to open file!"); // 响应失败}} else {httpd_send_response(hs, "HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\n\r\nInvalid request body!"); // 响应无效请求}
}

说明

  • 使用 httpd_read_request_body(hs, buf, sizeof(buf)) 读取 HTTP 请求体中的文件数据。
  • 使用 FATFS API f_open() 创建或打开文件,然后使用 f_write() 写入数据。
  • 根据操作结果,发送不同的 HTTP 响应。

2. 获取文件列表的代码

接下来,我们需要实现一个功能来获取当前存储设备中的所有文件。

#include "ff.h" // FATFS 头文件// 处理文件列表请求
static void handle_file_list(struct httpd_state *hs) {DIR dir;FILINFO fno;FRESULT res;char response[1024];int response_length = 0;// 打开目录res = f_opendir(&dir, "/"); // 假设所有文件都在根目录if (res == FR_OK) {response_length += snprintf(response + response_length, sizeof(response) - response_length, "[");while ((res = f_readdir(&dir, &fno)) == FR_OK && fno.fname[0] != 0) {if (response_length > 1) {response_length += snprintf(response + response_length, sizeof(response) - response_length, ",");}response_length += snprintf(response + response_length, sizeof(response) - response_length, "\"%s\"", fno.fname);}response_length += snprintf(response + response_length, sizeof(response) - response_length, "]");f_closedir(&dir);httpd_send_response(hs, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n");httpd_send_response(hs, response); // 发送文件列表} else {httpd_send_response(hs, "HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain\r\n\r\nFailed to open directory!"); // 响应失败}
}

说明

  • 使用 f_opendir() 打开根目录,使用 f_readdir() 读取目录中的文件。
  • 将文件名格式化为 JSON 格式的字符串,返回给前端。
  • 发送 HTTP 响应,内容类型为 application/json

3. 绑定 HTTP 请求处理

在 HTTP 服务器初始化时,我们需要将上传和文件列表请求的处理函数绑定到相应的 URL。

void start_http_server(void) {httpd_init(); // 初始化 HTTP 服务器// 绑定请求处理函数httpd_register_uri("/upload", handle_file_upload, HTTP_POST); // 处理文件上传httpd_register_uri("/files", handle_file_list, HTTP_GET); // 获取文件列表
}

说明

  • httpd_register_uri() 函数用于将请求 URL 与处理函数进行绑定。
  • /upload URL 用于处理文件上传请求,/files URL 用于获取文件列表。

项目总结

在本项目中,我们成功地搭建了一个基于 STM32 的 NAS(网络附加存储)私盘,利用 STM32 开发板的强大功能和灵活性,结合 LwIP 协议栈和 FATFS 文件系统,实现了文件的上传、下载和管理。以下是本项目的关键要点和收获:

1. 硬件与软件的结合

通过选择适合的 STM32 开发板(如 STM32F407 或 STM32F746),并配合外部 SATA 硬盘和网络模块(如以太网或 Wi-Fi),我们有效地创建了一个功能强大的 NAS 解决方案。硬件部分的选择对于系统的稳定性和性能至关重要,而软件部分则利用了 STM32 HAL 库、FATFS 文件系统和 LwIP 协议栈,使得硬件功能得以充分发挥。

2. 文件管理功能

我们成功实现了基本的文件管理功能,包括文件的上传、下载和列表展示。通过使用 FATFS 库,我们能够方便地对外接存储进行文件操作,这为用户在 NAS 上进行文件管理提供了便利。

3. Web 前端交互

通过搭建简单的 Web 前端界面,用户能够直观地与 NAS 进行交互。使用 HTML、CSS 和 JavaScript,我们实现了文件上传和文件列表展示功能,使得用户在浏览器中就可以方便地操作存储在 STM32 上的文件。此外,利用 AJAX 技术,我们实现了无刷新数据交互,提升了用户体验。

4. 网络通信实现

使用 LwIP 协议栈,我们为 STM32 开发板实现了网络通信功能。通过 HTTP 协议,前端与后端的交互得以顺利进行。我们实现了对文件上传和文件列表请求的处理,使得用户能够通过网络访问 NAS 中的文件。

相关文章:

基于 STM32 的 NAS私有云盘搭建:集成LwIP 协议、HTTP/HTTPS、WEB前端技术栈(代码示例)

项目概述 在本项目中&#xff0c;我们将搭建一个基于 STM32 的 NAS&#xff08;网络附加存储&#xff09;私盘&#xff0c;通过网络访问存储在外部 SATA 硬盘上的文件。该项目将使用 STM32 开发板、外接 SATA 硬盘、LwIP 协议栈以及 FATFS 文件系统来实现文件的上传、下载和管…...

蓝屏?死机?爆CPU?多开卡顿?你有关心过你的硬盘吗?

上来先叠甲 蓝屏、死机、爆cpu、多开卡顿&#xff0c;不一定是硬盘的问题&#xff0c;只是硬盘有问题都可能会引起这些现象&#xff0c;所以不要遇到这些问题就一定认为是硬盘的问题然后说我说的&#xff0c;只是给你一个排除问题的思路。本文会采用比较通俗所以不太专业的角度…...

Flutter开发报错error: unable to unlink old ‘pubspec.yaml‘: Invalid argument

背景&#xff1a;主分支master&#xff0c;然后每人1个分支&#xff0c;每次push到自己分支后&#xff0c;再提mr到master。 于是每次提交前要先git merge origin/master。 有时候会报这个错误&#xff0c;无法merge 原因&#xff1a;很简单&#xff0c;就是pubspec.yaml这个文…...

零基础进程最详解:进程状态、僵尸进程、孤儿进程、阻塞态、挂起态、进程切换、进程常用命令、进程创建、队列优先级

目录 强烈建议全文阅读&#xff01;&#xff01;&#xff01; 强烈建议全文阅读&#xff01;&#xff01;&#xff01; 强烈建议全文阅读&#xff01;&#xff01;&#xff01; 一、进程状态 二、僵尸和孤儿进程 1、僵尸进程 Z&#xff08;zombie&#xff09; 2、孤儿进…...

Redis的分布式锁

目录 一、定义与原理 基于Redis的分布式锁 获取锁 释放锁 锁误删问题&#xff1a;因为key值一样,将别人的锁删掉了 锁误判问题二&#xff1a;判断锁和释放锁不是原子性的 Lua脚本 分布式锁&#xff1a;满足分布式系统或集群模式下多进程可见并且互斥的锁 分布式锁的优点…...

C++笔记---类和对象

1. 类的定义 类是C中的一种自定义类型&#xff0c;是某个具体事物或概念的抽象化代码表示&#xff0c;通过类的成员&#xff08;变量函数/方法&#xff09;&#xff0c;可以表征出事物或概念的特征。 1.1 类定义的格式 class Stack { public:// 成员函数void Init(int n 4)…...

全国区块链职业技能大赛样题第9套后端源码

后端源码地址:https://blog.csdn.net/Qhx20040819/article/details/140746050 前端源码地址:https://blog.csdn.net/Qhx20040819/article/details/140746216 智能合约+数据库表设计:https://blog.csdn.net/Qhx20040819/article/details/140746646 项目预览 登录 用户管理...

3个功能强大的PDF转换工具,免费试用

给大家分享3个功能强大能满足更高需求的PDF转换工具&#xff0c;都提供免费的试用机会。 1.嗨动PDF编辑器 一款多功能的PDF编辑软件&#xff0c;集PDF阅读、PDF转换、PDF编辑功能为一体。支持转换的格式多样&#xff0c;转换速度快&#xff0c;转换后的排版和内容与原文保持一…...

表单修改数字输入框保留小数点

1.在表单设计打开修改的表单 2.打开需要修改的字段 3.按F12&#xff0c;进入“开发模式” 4.开启“开发者工具”左上角检索工具 开启&#xff1a;鼠标左键点击&#xff0c;当图标颜色为蓝色 关闭&#xff1a;鼠标左键点击&#xff0c;当图标颜色为灰色 5.鼠标移动到需要修改的…...

[VS Code扩展]写一个代码片段管理插件(一):介绍与界面搭建

文章目录 VS Code扩展机制项目搭建创建UI元素活动栏按钮主边栏视图主边栏工具栏按钮侧边栏右键菜单编辑器右键菜单 项目地址 [VS Code扩展]写一个代码片段管理插件&#xff08;一&#xff09;&#xff1a;介绍与界面搭建[VS Code扩展]写一个代码片段管理插件&#xff08;二&…...

vxe grid slots 用法

官方例子&#xff1a;Vxe Table v3.8 {field: num1,title: Num1,showHeaderOverflow: true,filters: [{ data: }],editRender: { autofocus: .my-input },slots: {// 使用插槽模板渲染default: num1_default,header: num1_header,footer: num1_footer,filter: num1_filter,edi…...

【网络】基于UDP协议的聊天室(第二篇)

目录 UDP服务器 UDP客户端 在C中&#xff0c;使用UDP协议进行网络通信通常涉及到socket编程。下面我将给出基于UDP的简单的客户端和服务器示例代码。这些示例将使用C标准库以及POSIX套接字接口&#xff08;主要适用于Linux和类Unix系统&#xff09;。如果你在使用Windows&…...

【SpringBoot3】场景整合(实战)

0 环境准备 0.0 云服务器 阿里云、腾讯云、华为云 服务器开通&#xff1b; 按量付费&#xff0c;省钱省心 安装以下组件&#xff1a;docker、redis、kafka、prometheus、grafana 下载windterm&#xff1a; https://github.com/kingToolbox/WindTerm/releases/download/2.5…...

【全网最全最详细】MYSQL 面试题大全(上)

目录 一、关系型数据库和非关系型数据库主要有哪些区别? 二、MYSQL的数据存储一定是基于硬盘的吗? 三、InnoDB和MyISAM有什么区别? 四、MyISAM的索引结构是怎么样的?存在的问题是什么? 五、char和varchar的区别? 六、MYSQL 5.x和8.0有什么区别? 七、为什么大厂不…...

【C语言】程序环境,预处理,编译,汇编,链接详细介绍,其中预处理阶段重点讲解

目录 程序环境 翻译环境 1. 翻译环境的两个过程 2. 编译过程的三个阶段 执行环境 预处理(预编译) 1. 预定义符号 2. #define 2.1 用 #define 定义标识符(符号) 2.2 用 #define 定义宏 2.3 #define 的替换规则 2.4 # 和 ## 的用法 2.5 宏和函数 2.6 #undef …...

人生低谷来撸C#--021 多线程

1、概念 线程 被定义为程序的执行路径。每个线程都定义了一个独特的控制流。如果您的应用程序涉及到复杂的和耗时的操作&#xff0c;那么设置不同的线程执行路径往往是有益的&#xff0c;每个线程执行特定的工作。 线程是轻量级进程。一个使用线程的常见实例是现代操作系统中…...

【优秀python django系统案例】基于python的医院挂号管理系统,角色包括医生、患者、管理员三种

随着信息技术的迅猛发展&#xff0c;传统的医院挂号管理方式面临着效率低下、排队时间长、信息不对称等诸多问题。这些问题不仅影响患者的就医体验&#xff0c;也加重了医院工作人员的负担。在此背景下&#xff0c;基于Python的医院挂号管理系统应运而生。该系统旨在通过信息化…...

硬盘数据丢失不再怕,四大恢复工具帮你轻松逆转局面!

硬盘故障、误删文件、病毒攻击等原因导致数据丢失的情况时有发生。面对这种情况&#xff0c;如何高效、快速地进行硬盘数据恢复呢&#xff1f;接下来几款好用的数据恢复软件推荐给大家。 一、福昕数据恢复&#xff1a;全方位恢复&#xff0c;让数据无遗漏 链接&#xff1a;ww…...

自定义封装日历组件

自定义日历 工作需要&#xff0c;但现有框架封装的日历无法满足需求&#xff0c;又找不到更好的插件&#xff0c;所以准备自己封装一个。 效果图和说明 一个很简易版的demo日历&#xff0c;本文只提供最基本的功能代码&#xff0c;便于阅读二开。 新建calendar.vue文件 <…...

【大模型】【面试】独家总结表格

问题解答你能解释一下Transformer架构及其在大型语言模型中的作用吗?Transformer架构是一种深度神经网络架构,于2017年由Vaswani等人在他们的论文“Attention is All You Need”中首次提出。自那以后,它已成为大型语言模型(如BERT和GPT)最常用的架构。 Transformer架构使用…...

C# 6.定时器 timer

使用控件&#xff1a; 开启定时器&#xff1a;timer1.Start(); 关闭定时器&#xff1a;timer1.Stop(); 定时间时间间隔:Interval timer1.Interval 1000; Interva等于1000是每一秒刷新一次 定时器默认时间间隔是100ms 代码创建定时器 ①创建 Timer t1 new Timer(); …...

有了 createSlice,还有必要使用 createReducer 吗?什么情况需要 createReducer 呢?

通常情况下&#xff0c;使用 createSlice 已经足够满足大多数需求&#xff0c;而不需要直接使用 createReducer。但是&#xff0c;在某些特定场景下&#xff0c;createReducer 仍然有其用处&#xff1a; 更细粒度的控制&#xff1a; 当你需要对 reducer 的行为进行更精细的控制…...

怎么搭建AI带货直播间生成虚拟主播?

随着电商直播带货的热潮不断升温&#xff0c;虚拟主播逐渐崭露头角&#xff0c;成为电商直播领域的新宠&#xff0c;相较于真人主播&#xff0c;虚拟主播具备无档期风险、人设稳定可控、24小时不间断直播等显著优势。 本文将深入探讨如何搭建一个AI带货直播间&#xff0c;并详…...

设计模式的原则

设计模式的原则通常包括以下几种核心原则&#xff1a; 单一职责原则 (SRP)&#xff1a;一个类应该只有一个单一的职责&#xff0c;即该类应该只有一个引起它变化的原因。这样可以减少类之间的耦合&#xff0c;使得系统更加易于维护和扩展。 开放/封闭原则 (OCP)&#xff1a;软…...

RocketMQ与RabbitMQ的区别:技术选型指南

在现代分布式系统和微服务架构中&#xff0c;消息队列&#xff08;Message Queue&#xff0c;简称MQ&#xff09;扮演着至关重要的角色。消息队列用于实现系统间的异步通信、解耦、削峰填谷等功能。目前常见的MQ实现包括ActiveMQ、RabbitMQ、RocketMQ和Kafka。本文将重点对比Ro…...

小白也能懂:SQL注入攻击基础与防护指南

SQL注入是一种针对数据库的攻击方式&#xff0c;攻击者通过在Web表单、URL参数或其他用户输入的地方插入恶意SQL代码&#xff0c;以此绕过应用程序的验证机制&#xff0c;直接与后台数据库交互。这种攻击可以导致攻击者无授权地查看、修改或删除数据库中的数据&#xff0c;甚至…...

【Hot100】LeetCode—76. 最小覆盖子串

题目 原题链接&#xff1a;76. 最小覆盖子串 1- 思路 利用两个哈希表解决分为 &#xff1a;① 初始化哈希表、②遍历 s&#xff0c;处理当前元素&#xff0c;判断当前字符是否有效、③收缩窗口、④更新最小覆盖子串 2- 实现 ⭐76. 最小覆盖子串——题解思路 class Solution …...

删除排序链表中的重复元素 II(LeetCode)

题目 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 解题 class ListNode:def __init__(self, val0, nextNone):self.val valself.next nextclass Solution:def deleteDuplicates(self…...

【Java】解决如何将Http转为Https加密输出

目录 HTTP转HTTPS一、 获取 SSL/TLS 证书二、 安装证书2.1 Apache2.2 Nginx 三、更新网站配置四. 更新网站链接五. 检查并测试六. 自动续期&#xff08;针对 Lets Encrypt&#xff09; HTTP转HTTPS 将网站从 HTTP 转换为 HTTPS 能够加密数据传输&#xff0c;还能提高搜索引擎排…...

二叉树链式结构的实现(递归的暴力美学!!)

前言 Hello,小伙伴们。你们的作者菌又回来了&#xff0c;前些时间我们刚学习完二叉树的顺序结构&#xff0c;今天我们就趁热打铁&#xff0c;继续我们二叉树链式结构的学习。我们上期有提到&#xff0c;二叉树的的底层结构可以选为数组和链表&#xff0c;顺序结构我们选用的数…...

做自己的直播网站/潍坊网站关键词推广

clean the macOS, no more input installed;in Xcode, run debug;drag debug app to ~/library/input methods;to systray, add input;in Xcode, active the input;it works!if no effect, go to 1, and then restar macOS, go to 1....

小说网站静态页面模板/长沙专业做网站公司

最近研究设置数据&#xff0c;稍微总结一下&#xff0c;以后继续补充&#xff1a; 在一个18摸AIX上跑的一台11g的库&#xff0c;检查的时候发明视图V$UNDOSTAT的数据很诡异&#xff0c;第1条的记载时光段竟然一直没有被切割过&#xff0c;开始时光是2011-12-26 09:52:08结束时光…...

中国建设工程信息网清欠/深圳seo优化排名

K的因子中只包含2 3 5。满足条件的前10个数是&#xff1a;2,3,4,5,6,8,9,10,12,15。所有这样的K组成了一个序列S&#xff0c;现在给出一个数n&#xff0c;求S中 > 给定数的最小的数。例如&#xff1a;n 13&#xff0c;S中 > 13的最小的数是15&#xff0c;所以输出15。In…...

wordpress分类自定义title/网络销售真恶心

题目描述 学校植树节开展植树活动&#xff0c;已知CoCo所在的班级分到树苗m株&#xff0c;班里参加植树的同学有n人&#xff08;m>n&#xff09;&#xff0c;请问每位同学平均可以植树几株&#xff1f;还有几株剩余&#xff1f;输入要求 输入两个整数m和n&#xff0c;分别…...

嘉兴高端网站建设/百度推广登录平台

在上一文中&#xff0c;论述两个.Net Framework对null应用不够合理的例子。大家评论中&#xff0c;给出了不少指导性意见&#xff0c;这里也对.Net中null的使用规范作一下总结。 1. Empty代表瓶子是空的&#xff0c;null代表瓶子都没有 首先要明确你的“瓶子”是什么&#xff0…...

3g网站建设/怎么建立自己的网站

图片自己随便扣的大家不要见笑&#xff01; 本例子所用知识参考 http://www.w3school.com.cn/css3/css3_animation.asp 直接上代码 直接复制粘贴就可用 这个是body里面的代码 <body><section><div class"cloud large"></div> <div class&…...