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

【网络云盘客户端】——上传文件的功能的实现

目录

上传文件功能的实现

uploadtask的设计

设置上传的槽函数

uploadFileAction接口

 uploadFile接口

定时上传文件

进度条的设计


上传文件功能的实现

上传文件功能实现

1.双击 ”上传文件 “的 QListWidgetItem 或者 点击 “上传” 菜单项 都会弹出一个文件对话框

 2.在文件对话框选中对应的文件,保存所有文件的路径(在对话框中可以选中多个文件)

3.将对应的文件存放到  uploadtask* m_uploadtask中(uploadtask 是一个上传文件队列类型

4.定义m_uploadTimer定时器,每0.5秒调用 uploadFileAction 进行上传文件。

5.uploadFileAction中先发送一个 md5 http请求给服务器

  • 如果文件存在服务器,则 秒传成功,不需要将文件内容发送到服务器上
  • 如果文件不存在服务器,则再发送一个upload的请求,将文件的内容上传到服务器上。

6.妙传失败,调用 uploadFile 接口,将文件内容上传到服务器上。

uploadtask的设计

1.UploadFileInfo 是上传文件的信息的结构体


#define UPLOAD_NOT          0   //未上传
#define UPLOADING           1   //正在上传
#define UPLOAD_FINISHED     2   //上传完成
#define UPLOAD_FAILD        3   //上传失败
#define UPLOAF_FILE_EXISTE  4   //上传的文件已存在struct UploadFileInfo
{QString md5;            //文件的md5值QString fileName;       //文件名称QString filePath;       //文件路径qint64 size;            //文件大小FileDataProgress *fdp;  //进度条int uploadStatus;       //0.未上传,1.正在上传,2.上传完成
};

2.UploadTask上传任务 列表类,该 任务列表 存储的是即将上传的文件的信息 UploadFileInfo

//uploadtask.h文件//上传任务列表类, 单例模式
class UploadTask
{
public ://获取UploadTask唯一实例对象static UploadTask* getInstance();//添加文件到上传任务列表中int appendUploadTask(QString filePath);//判断任务列表是否为空bool isEmpty();//取出任务UploadFileInfo* takeTask();//删除任务void delUploadTask();//清空上传任务列表列表void clearList();
private:UploadTask();~UploadTask();//静态数据成员,类中声明,类外必须定义static UploadTask* m_instance;
private:QList<UploadFileInfo*> m_fileList;
};//uploadtask.cpp文件//添加文件到上传任务列表中
int uploadtask::appendUploadTask(QString filePath)
{QFileInfo* fileinfo=new QFileInfo(filePath);if(fileinfo->size()>30*1024*1024){//如果文件大于30mb,则放弃该文件delete fileinfo;return -1;}//新建一个UploadFileInfo对象UploadFileInfo* uploadFileInfo=new UploadFileInfo;uploadFileInfo->size=fileinfo->size();uploadFileInfo->fileName=fileinfo->fileName();uploadFileInfo->filePath=filePath;uploadFileInfo->md5=Common::getInstant()->getFileMd5(filePath);uploadFileInfo->uploadStatus=UPLOAD_NOT;//设置未上传状态filedataProgress* upProgress=new filedataProgress;upProgress->setName(uploadFileInfo->fileName);uploadFileInfo->fdp=upProgress;//将进度条插入到上传列表中uploadlayout::getInstant()->getVLayout()->insertWidget(0,upProgress);m_filelist.append(uploadFileInfo);
}//判断任务列表是否为空
bool uploadtask::isEmpty()
{return m_filelist.empty();
}//取出任务
UploadFileInfo* uploadtask::takeTask()
{if(m_filelist.empty()){return nullptr;}UploadFileInfo* temp=m_filelist.at(0);return temp;
}//删除任务
void uploadtask::delUploadTask()
{//1.取出任务,判断该任务的状态,如果是上传完成,上传失败,上传成功,该任务是会被删除掉//2.将该任务从列表中移除//3.删除进度条,并删除该任务的资源if(isEmpty()){return;}UploadFileInfo* temp=m_filelist.at(0);if(temp->uploadStatus==UPLOAD_FINISHED||temp->uploadStatus==UPLOAD_FAILD||temp->uploadStatus==UPLOAF_FILE_EXISTE  ){//删除该任务qDebug()<<"删除任务";m_filelist.removeAt(0);//将进度条从布局中移除uploadlayout::getInstant()->getVLayout()->removeWidget(temp->fdp);delete temp->fdp;delete temp;}
}//清空任务列表
void uploadtask::clearList()
{int len=m_filelist.size();for(int i=0;i<len;i++){UploadFileInfo* temp=m_filelist.at(0);m_filelist.removeAt(0);uploadlayout::getInstant()->getVLayout()->removeWidget(temp->fdp);//将进度条从布局中移除delete temp->fdp;delete temp;}
}

设置上传的槽函数

点击 “上传文件" 的QListWidgetItem,将文件的上传任务 添加 到 上传队列中。

//设置“上传文件”QListWidgetItem的槽函数
//双击QListWidget窗口中的控件,则会发出一个itemDoubleClicked信号
connect(ui->listWidget,&QListWidget::itemDoubleClicked,this,[=](QListWidgetItem *item){if(item->text()=="上传文件"){addUploadFile();}});//设置“上传”菜单项的槽函数connect(m_uploadAction,&QAction::triggered,this,[=]{addUploadFile();qDebug()<<"上传";
});//添加上传文件
void myfile::addUploadFile()
{//getOpenFileNames可以获取多个文件的路径QStringList filelist=QFileDialog::getOpenFileNames();for(int i=0;i<filelist.size();i++){//将文件添加到m_uploadtask中int res=m_uploadtask->appendUploadTask(filelist[i]);if(res==-1){//服务器设置最多只能上传30m大小的文件QMessageBox::warning(this,"警告","文件大小大于30m");}}
}

uploadFileAction接口

  • uploadFileActionm_uploadtask获取一个UploadFileInfo对象
  • 在根据UploadFileInfo对象信2息发送一个 HTTP请求给服务器去验证文件是否存在
POST http://119.23.41.13:80/md5 HTTP/1.1
Content-Type: application/json{"fileName": "111.rtf", //文件名"md5": "8274425de767b30b2fff1124ab54abb5",//文件md5值,标识文件的唯一性"token": "7b4b4922958c5cbb153df2668b714144",//验证用户身份"user": "zhangsan"//用户信息
}

客户端根据服务器返回的 code 做出相应的动作。 

​
"code":"005"  //上传的文件已存在(别的用户正在上传该文件)
"code":"006"  //秒传成功,文件已经存在
"code":"007"  // 秒传失败,文件不存在,需要调用uploadFile上传文件,
"code":"011"   //"Token 验证失败,身份过期​

 

//获取m_uploadtask中的一个上传任务
void myfile::uploadFileAction()
{if(m_uploadtask->isEmpty()){//任务列表为空// qDebug()<<"任务列表为空";return;}UploadFileInfo* uploadFileInfo=m_uploadtask->takeTask();//先进行快传,判断文件是否已经上传成功//封装http请求//如果该文件没有上传,则发送请求if(uploadFileInfo->uploadStatus==UPLOAD_NOT){uploadFileInfo->uploadStatus=UPLOADING;QNetworkRequest request;//从配置文件中获取到ip地址和port端口号QString ip=Common::getInstant()->getConfValue("web_server","ip");QString port=Common::getInstant()->getConfValue("web_server","port");QString url = QString("http://%1:%2/md5").arg(ip).arg(port);request.setUrl(QUrl(url));//设置文件类型request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));//将data数据以QJson的格式发送给服务器QJsonObject object;object.insert("user", m_logininfo->user());object.insert("token", m_logininfo->token());object.insert("md5",uploadFileInfo->md5);object.insert("fileName",uploadFileInfo->fileName);QJsonDocument doc(object);QByteArray data=doc.toJson();//发送请求// qDebug()<<data;QNetworkReply* rely=m_manager->post(request,data);connect(rely,&QNetworkReply::readyRead,this,[=]{//响应到达,读取所有的数据QByteArray s=rely->readAll();qDebug() << "服务器返回数据:" << QString(s);//将s数据转换为Json对象QJsonParseError err;QJsonDocument document=QJsonDocument::fromJson(s,&err);if(err.error!=QJsonParseError::NoError){qDebug()<<"QJson格式错误";return;}//将QJson字符串转换为QJson对象QJsonObject object1;object1=document.object();//获取状态码QString value1=object1["code"].toString();if(value1=="005"){qDebug()<<"文件已经存在";//文件正在上传uploadFileInfo->uploadStatus=UPLOAF_FILE_EXISTE;Common::getInstant()->writeRecord(m_logininfo->user(),uploadFileInfo->fileName,value1);m_uploadtask->delUploadTask();return;}if(value1=="006"){uploadFileInfo->uploadStatus=UPLOAF_FILE_EXISTE;Common::getInstant()->writeRecord(m_logininfo->user(),uploadFileInfo->fileName,value1);m_uploadtask->delUploadTask();qDebug()<<"妙传成功";}if(value1=="007"){//qDebug()<<"上传文件";//文件没有上传到服务器上,需要将文件上传到服务器上uploadFile(uploadFileInfo);}if(value1=="111"){Common::getInstant()->writeRecord(m_logininfo->user(),uploadFileInfo->fileName,value1);qDebug()<<"token验证失败";}});}
}

 uploadFile接口

uploadFile是发送一个 http请求 将文件中数据发送给服务器,服务器会将其进行保存。

POST http://119.23.41.13:80/upload HTTP/1.1
Content-Type: application/json------WebKitFormBoundaryNr0Jm9D3w0GCiG9g //文件边界线
Content-Disposition: form-data; user="zhangsan" filename="111.rtf" md5="8274425de767b30b2fff1124ab54abb5" size=7
Content-Type: application/octet-stream文件数据
------WebKitFormBoundaryNr0Jm9D3w0GCiG9g //文件边界线

服务器返回值:

"code":"008"
"code":"009"

 

//将文件上传到服务器上
/*
------WebKitFormBoundaryDQAR0QX1ojAyzAre\r\n
Content-Disposition: form-data; name="file"; filename="logo.png"\r\n
Content-Type: image/png\r\n
\r\n
真正的文件内容\r\n
------WebKitFormBoundaryDQAR0QX1ojAyzAre
*/
//将文件内容上传到服务器上
void myfile::uploadFile(UploadFileInfo *uploadFileInfo)
{QFile file(uploadFileInfo->filePath);file.open(QIODevice::ReadOnly | QIODevice::Text);logininfoinstance *login = logininfoinstance::getInstant();//getBoundary接口是随机生成一个文件边界线QString boundary = m_common->getBoundary();QByteArray data;data.append(boundary);data.append("\r\n");data.append("Content-Disposition: form-data; ");data.append(QString("user=\"%1\" filename=\"%2\" md5=\"%3\" size=%4").arg(login->user()).arg(uploadFileInfo->fileName).arg(uploadFileInfo->md5).arg(uploadFileInfo->size));data.append("\r\n");data.append("Content-Type: application/octet-stream");data.append("\r\n");data.append("\r\n");//上传中的数据data.append(file.readAll());data.append("\r\n");data.append(boundary);//文件边界线if (file.isOpen()) {file.close();}QString url = QString("http://%1:%2/upload").arg(login->ip()).arg(login->port());QNetworkRequest request;request.setUrl(url);request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));//发送http请求QNetworkReply *reply = m_manager->post(request, data);if (reply == NULL) {qDebug() << "请求失败";return;}//显示文件上传进度connect(reply, &QNetworkReply::uploadProgress, this, [=](qint64 bytesSent, qint64 bytesTotal){//bytesSent 上传的字节数//bytesTotal 文件需要上传的总字节数if (bytesTotal != 0) {//显示进度条(设置进度条)uploadFileInfo->fdp->setValue(bytesSent, bytesTotal);}});connect(reply, &QNetworkReply::finished, this, [=](){//文件上传完成后if (reply->error() != QNetworkReply::NoError) {qDebug() << reply->errorString();} else {QByteArray s=reply->readAll();/*008: 上传成功009: 上传失败*///响应到达,读取所有的数据// qDebug() << "服务器返回数据:" << QString(s);//将s数据转换为Json对象QJsonParseError err;QJsonDocument document=QJsonDocument::fromJson(s,&err);if(err.error!=QJsonParseError::NoError){qDebug()<<"QJson格式错误";return;}//将QJson字符串转换为QJson对象QJsonObject object1;object1=document.object();//获取状态码QString value1=object1["code"].toString();if (value1== "008") {qDebug() << "上传成功";uploadFileInfo->uploadStatus=UPLOAD_FINISHED;getFileCount(Normal);} else if (value1 == "009") {uploadFileInfo->uploadStatus=UPLOAD_FAILD;qDebug() << "上传失败";}//将传输记录记录到文件中Common::getInstant()->writeRecord(login->user(),uploadFileInfo->fileName,value1);//   writeRecord(QString user, QString fileName, QString code, QString path)}m_uploadtask->delUploadTask();reply->deleteLater();});
}

 

定时上传文件

定义一个定时器,定时器每0.5秒 调用一次uploadFileAction函数,

    //设置每0.5秒调用uploadFileActionm_uploadTimer.start(500);connect(&m_uploadTimer,&QTimer::timeout,this,[=](){uploadFileAction();});

进度条的设计

自定义一个进度条类型filedataProgress ,包括filedataProgress.h ,filedataProgress.cpp,filedataProgress.ui 文件.

filedataProgress.ui界面设计:

        

 

//filedataProgress.cpp文件
//设置文件名
void filedataProgress::setName(QString name)
{ui->label->setText(name);
}
//设置进度条数据
void filedataProgress::setValue(int value,int maxValue)
{ui->progressBar->setValue(value*100/maxValue);
}

当上传任务添加到上传列表时,就将进度条显示到 上传列表中,等待客户端上传文件。

uploadFile接口 中需要设置 QNetWorkReply的uploadProgress信号,将上传的进度显示到进度条上。。QNetWorkReply每 当上传一次文件数据,则会发出uploadProgress信号 

注意: bytesTotal 不能为 0,如果为 0,则会崩溃。

        //显示文件上传进度connect(reply, &QNetworkReply::uploadProgress, this, [=](qint64 bytesSent, qint64 bytesTotal){//bytesSent 上传的字节数//bytesTotal 文件需要上传的总字节数if (bytesTotal != 0) {//显示进度条(设置进度条)uploadFileInfo->fdp->setValue(bytesSent, bytesTotal);}});

相关文章:

【网络云盘客户端】——上传文件的功能的实现

目录 上传文件功能的实现 uploadtask的设计 设置上传的槽函数 uploadFileAction接口 uploadFile接口 定时上传文件 进度条的设计 上传文件功能的实现 上传文件功能实现 1.双击 ”上传文件 “的 QListWidgetItem 或者 点击 “上传” 菜单项 都会弹出一个文件对话框 2.在文…...

WebView2对比CefSharp的超强优势

第一次使用了CefSharp组件&#xff0c;集成开发结束后&#xff0c;测试及使用过程中遇到了一些无法处理的bug及严重的性能问题。然后又测试对比了其他多种组件&#xff0c;具体情况可以阅读我的博客​ ​《.NET桌面程序集成Web网页开发的十种解决方案》​​。最终选用了微软新出…...

前端需要知道的计算机网络知识

1 Web 机制 无论通过有线方式 (通常是网线) 还是无线方式&#xff08;比如 wifi 或蓝牙)&#xff0c;通信需要进行连接&#xff0c;网络上的每台计算机需要链接到路由器&#xff08;router&#xff09;。 路由器确保从一台计算机上发出的一条信息可以到达正确的计算机。计算机…...

[2023杭电多校5 1005] Snake (生成函数)

题意 有 n n n 个标号为 1 , 2 , ⋯ , n 1,2,\cdots,n 1,2,⋯,n 的球&#xff0c;放到 m m m 个无标号盒子 (盒内顺序有标号)&#xff0c;且每个盒子球数不超过 k k k&#xff0c;求方案数对 998 244 353 998\,244\,353 998244353 取模。 1 ≤ m , k ≤ n ≤ 1 0 6 1 \le…...

【MyBtis】各种查询功能

目录 【MyBtis】配置和映射 11.1 示例:实现表数据的增、删、改、查 1.创建工程mybatis_DML demo 2.创建数据库操作的工具类&#xff1a;DBOperatorMgr.java 3.创建映射接口 4.创建XML映射文件 5.测试 【MyBtis】配置和映射 MyBatis 的真正强大之外在于它的映射语句&#xf…...

H5打包封装小程序系统开发

H5打包封装小程序系统开发 H5打包封装小程序系统开发是指将H5页面打包封装成小程序的开发过程。下面是一个简单的步骤&#xff1a; 准备工作&#xff1a;首先&#xff0c;需要准备好H5页面的代码和资源文件。确保H5页面在浏览器中正常运行&#xff0c;并且没有依赖于浏览器特…...

SpringBoot集成jasypt,加密yml配置文件

SpringBoot集成jasypt&#xff0c;加密yml配置文件 一、pom配置二、生成密文代码三、配置3.1、yml加密配置3.2、密文配置3.3、启动配置3.4、部署配置 四、遇到的一些坑 最新项目安全检测&#xff0c;发现配置文件中数据库密码&#xff0c;redis密码仍处理明文状态 一、pom配置…...

【C++】模板(初阶)

1、泛型编程 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础 2、函数模板 函数模板代表了一个函数家族&#xff0c;该函数模板与类型无关&#xff0c;在使用时被参数化&#xff0c;根据实参类型产生函数的特定类型版本…...

windows下的txt文档,传到ubuntu后,每行后面出现^M,怎么处理?

问题背景&#xff1a;windows下pycharm生成的txt文档&#xff0c;传到ubuntu后&#xff0c;每行后面出现^M 用vim打开显示 使用cat -A filename显示如下 参考https://www.lmlphp.com/user/16697/article/item/579325/给出的几种方法 方法一、dos2unix filename。服务器没装…...

LabVIEW FPGA开发实时滑动摩擦系统

LabVIEW FPGA开发实时滑动摩擦系统 由于非线性摩擦效应的建模和补偿的固有困难&#xff0c;摩擦系统的运动控制已被广泛研究。最近&#xff0c;人们更加关注滑动动力学和滑动定位&#xff0c;作为传统机器人定位的低成本和更灵活的驱动替代方案。摩擦控制器设计和适当选择基础…...

Prometheus服务器、Prometheus被监控端、Grafana、Prometheus服务器、Prometheus被监控端、Grafana

day03 day03Prometheus概述部署Prometheus服务器环境说明&#xff1a;配置时间安装Prometheus服务器添加被监控端部署通用的监控exporterGrafana概述部署Grafana展示node1的监控信息监控MySQL数据库配置MySQL配置mysql exporter配置mysql exporter配置prometheus监控mysql自动…...

常见的锁策略(面试八股文)

1.乐观锁vs悲观锁 乐观锁&#xff1a;预测该场景中不太会出现锁冲突的情况。&#xff08;后续做的工作会更少&#xff09; 悲观锁&#xff1a;预测该场景非常容易出现锁冲突&#xff08;后续做的工作会更多&#xff09; 锁冲突&#xff1a;多个线程同时尝试去获得同一把锁&…...

SO_KEEPALIVE、TCP_KEEPIDLE、TCP_KEEPINTVL、保活包

SO_KEEPALIVE SO_KEEPALIVE 是一个套接字选项&#xff0c;用于设置是否启用 keepalive 机制。在这段代码中没有涉及到 SO_KEEPALIVE 选项的设置。 当 SO_KEEPALIVE 被设置为非零值时&#xff0c;表示启用 keepalive 机制。keepalive 是一种用于检测连接是否仍然有效的机制。通…...

【phaser微信抖音小游戏开发005】画布上添加图片

特别注意&#xff1a;真机模拟的时候&#xff0c;尽量使用网络图片资源&#xff0c;不要在小程序源文件里面使用图片&#xff0c;会出现真机加载不成功&#xff0c;小程序包体积过大的问题。我们学习过程中&#xff0c;只是作为演示使用。 推荐使用场景&#xff1a; 背景图片…...

【设计模式——学习笔记】23种设计模式——外观模式Facade(原理讲解+应用场景介绍+案例介绍+Java代码实现)

文章目录 案例引入介绍基本介绍类图出场角色 案例实现案例一类图代码实现 案例二类图代码实现 外观模式在Mybatis源码中的应用总结文章说明 案例引入 在家庭影院中&#xff0c;要享受一场电影&#xff0c;需要如下步骤&#xff1a; 直接用遥控器&#xff1a;统筹各设备开关开…...

消息队列 -提供上层服务接口

目录 前言封装数据库封装内存操作内存的设计思想 应答模式 代码实现测试代码 前言 我们之前已经将 数据库 的操作 和文件的操作 都完成了, 但是对于上层调用来说, 并不关心是于数据库中存储数据还是往文件中存储数据, 因此 我们提供一个类, 封装一下 上述俩个类中的操作, 并将…...

maven引入本地jar包的简单方式【IDEA】【SpringBoot】

前言 想必点进来看这篇文章的各位&#xff0c;都是已经习惯了Maven从中央仓库或者阿里仓库直接拉取jar包进行使用。我也是&#x1f921;&#x1f921;。 前两天遇到一个工作场景&#xff0c;对接三方平台&#xff0c;结果对方就是提供的一个jar包下载链接&#xff0c;可给我整…...

【爬虫逆向案例】某易云音乐(评论)js逆向—— params、encSecKey解密

声明&#xff1a;本文只作学习研究&#xff0c;禁止用于非法用途&#xff0c;否则后果自负&#xff0c;如有侵权&#xff0c;请告知删除&#xff0c;谢谢&#xff01; 【爬虫逆向案例】某易云音乐&#xff08;评论&#xff09;js逆向—— params、encSecKey解密 1、前言2、行动…...

【uni-app】【Android studio】手把手教你运行uniapp项目到Android App

运行到Android App基座 选择运行到Android App基座 选择运行项目 1、连接手机&#xff0c;在手机上选择 传输文件。 2、打开 设置-> 关于本机 -> 版本信息->连续点击4-5次版本号 &#xff0c;输入手机密码&#xff0c;系统就进入了开发者模式。 3、设置 > 其他设…...

多线程(JavaEE初阶系列6)

目录 前言&#xff1a; 1.什么是线程池 2.标准库中的线程池 3.实现线程池 结束语&#xff1a; 前言&#xff1a; 在上一节中小编带着大家了解了一下Java标准库中的定时器的使用方式并给大家实现了一下&#xff0c;那么这节中小编将分享一下多线程中的线程池。给大家讲解一…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...