qt/LedOK/wProgramManager/threadsendpro.cpp

527 lines
15 KiB
C++
Raw Normal View History

2022-01-04 18:11:48 +08:00
#include "threadsendpro.h"
#include "QFileInfo"
#include <QHostAddress>
#include <QIODevice>
#include <QDir>
#include <QJsonArray>
#include <QDirIterator>
#include <QMessageBox>
#include <LoUIClass/x_uimsgboxok.h>
#include <QCoreApplication>
ThreadSendPro::ThreadSendPro(QString strProPathAndName,QString strIp,int iPort)
{
m_strProName=strProPathAndName;
m_strIp=strIp;
m_iPort=iPort;
}
ThreadSendPro::~ThreadSendPro()
{
}
void ThreadSendPro::run()
{
// 避免界面冻结
QCoreApplication::processEvents();
//如果关闭窗口,线程退出
if(bSendCloseFlag==true)
bSendCloseFlag=false;
else {
return;
}
sentAllBytes = 0;
loadBytes = LOADBYTES;
file = Q_NULLPTR;
send = new QTcpSocket();
connect(send, SIGNAL(connected()), this, SLOT(connect_sucessful()));
/* socket出错 -> 错误处理 */
connect(send, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(show_error(QAbstractSocket::SocketError)));
//发起连接设备
send->connectToHost(QHostAddress(m_strIp),m_iPort);
// emit sigSetLableText("connectToHost");
if(bSendCloseFlag)
return;
if(!send->waitForConnected(10000)) //等待连接返回
{
emit sigSetLableText("connect timeout");
//emit sigSetLableText("5");
return ;
}
sentAllBytes = 0;
//1.获取需要发送的文件列表,并获取到总的大小
m_NeedSendFileList=GetNeedFileList();
//2.等待应答
if(bSendCloseFlag)
return;
if(send->waitForReadyRead(5000))
{
if(bSendCloseFlag)
return;
QByteArray readBuf=send->read(send->bytesAvailable());
QJsonParseError parseJsonErr;
QJsonDocument document = QJsonDocument::fromJson(readBuf,&parseJsonErr);
if(!(parseJsonErr.error == QJsonParseError::NoError))
{
//qDebug()<<tr("解析json文件错误");
//return;
}
QJsonObject jsonObject = document.object();
QString strType=jsonObject["_type"].toString();
if(strType=="consult")
{
m_NeedSendFileList.clear();
QJsonArray bb=jsonObject["idList"].toArray();
for(int i=0;i<bb.count();i++)
{
m_NeedSendFileList.append(bb.at(i).toString());
}
m_bGetConsultAckFlag=true;
}
}
else {
}
qint64 iAllSize=GetNeedFileAllSize(strCurSendDir,m_NeedSendFileList);
//3.发送项目文件开始命令
QString m_strfileName=FindLocalFileFromPath(strCurSendDir,"program");
QFileInfo info(m_strfileName);
iAllSize+=info.size();
if(bSendCloseFlag)
return;
sendProJsonStart(iAllSize);
//QStringList strFileList;
//start_transfer_(strCurSendDir,&strFileList);
QString strtempAbsolutePath=info.absolutePath();
QString strTempRelativePath=strtempAbsolutePath.right(strtempAbsolutePath.length()-strCurSendDir.length());
if(bSendCloseFlag)
return;
SendFileHead(m_strfileName,strTempRelativePath);
if(bSendCloseFlag)
return;
SendFileData(m_strfileName);
if(bSendCloseFlag)
return;
SendFileEnd(m_strfileName);
//4.发送协商列表应答里的文件
if(bSendCloseFlag)
return;
start_transfer_byAckConsult(strCurSendDir,m_NeedSendFileList);
//5.发送结束
if(bSendCloseFlag)
return;
sendProJsonFinished();
if(bSendCloseFlag)
return;
if(send->waitForReadyRead(5000))
{
QByteArray readBuf=send->read(send->bytesAvailable());
QJsonParseError parseJsonErr;
QJsonDocument document = QJsonDocument::fromJson(readBuf,&parseJsonErr);
QJsonObject jsonObject = document.object();
QString strType=jsonObject["_type"].toString();
if(strType=="AckSuccess")
{
//readAckSempahore.release();
}
}
else {
}
if(send!=nullptr)
{
send->close();
bSendCloseFlag=true;
delete send;
}
// emit sigSetLableText("send finished");
qDebug()<<tr("get readAckSempahore");
}
int ThreadSendPro::connect_sucessful(){
// emit sigSetLableText(QString("Connection Established!"));
return 0;
}
QStringList ThreadSendPro::GetNeedFileList()
{
emit sigSetProgressValue(0); // 进度条归零
QFileInfo fileInfo(m_strProName);
QStringList strFileList;
strCurSendDir=fileInfo.absolutePath();
dirFileSize(strCurSendDir,&strFileList);
//发送节目列表协商
QJsonObject jsonXieShangObj;
QJsonArray aa;
for(int i=0;i<strFileList.count();i++)
{
QString strtemp=strFileList.at(i);
int iOffset=strtemp.indexOf(".");
strtemp=strtemp.left(iOffset);
aa.append(strtemp);
}
//aa.fromStringList(strFileList);
jsonXieShangObj.insert("_type", "consult");
jsonXieShangObj.insert("proName", fileInfo.fileName());
jsonXieShangObj.insert("idList",aa);
jsonXieShangObj.insert("zVer","xixun1");
QJsonDocument doc1;
doc1.setObject(jsonXieShangObj);
QByteArray sendArray1 = doc1.toJson(QJsonDocument::Compact);
send->write(sendArray1);
SynchronousSocketWrite();
return strFileList;
}
qint64 ThreadSendPro::GetNeedFileAllSize(const QString &path,QStringList list)
{
QDir dir(path);
qint64 size = 0;
//dir.entryInfoList(QDir::Files)返回文件信息
for (int m=0;m<list.count();m++)
{
QString strtempFileName=list.at(m);
if(strtempFileName!="program")
{
QString strFileAllPathName=FindLocalFileFromPath(path,strtempFileName);
QFileInfo fileInfo(strFileAllPathName);
size += fileInfo.size();
}
}
return size;
}
void ThreadSendPro::sendProJsonStart(qint64 iAllSize)
{
QJsonObject jsonPro;
jsonPro.insert("_type", "proStart");
QFileInfo fileInfo(m_strProName);
jsonPro.insert("proName", fileInfo.fileName());
emit sigSetProgressMax(iAllSize);
jsonPro.insert("proSize", iAllSize);
jsonPro.insert("zVer","xixun1");
QJsonDocument doc;
doc.setObject(jsonPro);
QByteArray sendArray = doc.toJson(QJsonDocument::Compact);
send->write(sendArray);
SynchronousSocketWrite();
}
void ThreadSendPro::sendProJsonFinished()
{
QJsonObject jsonPro;
jsonPro.insert("_type", "proEnd");
QFileInfo fileInfo(m_strProName);
jsonPro.insert("proName", fileInfo.fileName());
jsonPro.insert("zVer","xixun1");
QJsonDocument doc;
doc.setObject(jsonPro);
QByteArray sendArray = doc.toJson(QJsonDocument::Compact);
send->write(sendArray);
// send->flush();
SynchronousSocketWrite();
}
qint64 ThreadSendPro::dirFileSize(const QString &path,QStringList *list)
{
QDir dir(path);
qint64 size = 0;
//dir.entryInfoList(QDir::Files)返回文件信息
foreach(QFileInfo fileInfo, dir.entryInfoList(QDir::Files))
{
QString strOnlyFileName=fileInfo.fileName();
int iAlreadExistFlag=0;
for(int i=0;i<list->count();i++)
{
if(list->at(i)==strOnlyFileName)
{
iAlreadExistFlag=1;
}
}
if(iAlreadExistFlag==0)//不重复的文件才计入发送的总大小
{
list->append(strOnlyFileName);
//计算文件大小
size += fileInfo.size();
}
}
//dir.entryList(QDir::Dirs|QDir::NoDotAndDotDot)返回所有子目录,并进行过滤
foreach(QString subDir, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot))
{
//若存在子目录则递归调用dirFileSize()函数
size += dirFileSize(path + QDir::separator() + subDir,list);
}
return size;
}
void ThreadSendPro::start_transfer_byAckConsult(const QString &path,QStringList list)
{
QDir dir(path);
//dir.entryInfoList(QDir::Files)返回文件信息
for (int m=0;m<list.count();m++)
{
if(bSendCloseFlag)
return;
QString strtempFileName=list.at(m);
if(strtempFileName!="program")
{
QString m_strfileName=FindLocalFileFromPath(path,strtempFileName);
QFileInfo info(m_strfileName);
if(info.exists())
{
QString strtempAbsolutePath=info.absolutePath();
QString strTempRelativePath=strtempAbsolutePath.right(strtempAbsolutePath.length()-strCurSendDir.length());
if(SendFileHead(m_strfileName,strTempRelativePath)==false)
return;
if(SendFileData(m_strfileName)==false)
return;
if(SendFileEnd(m_strfileName)==false)
return;;
}
}
}
}
QString ThreadSendPro::FindLocalFileFromPath(const QString &strFilePath, const QString filename)
{
QStringList m_Filelist;//找到的文件存入此队列
if (strFilePath.isEmpty() || filename.isEmpty())
{
return "";
}
QDir dir;
QStringList filters;
filters << filename;//过滤条件,可以添加多个选项,可以匹配文件后缀等。我这里只是找指定文件
dir.setPath(strFilePath);
dir.setNameFilters(filters);//添加过滤器
//QDirIterator 此类可以很容易的返回指定目录的所有文件及文件夹,可以再递归遍历,也可以自动查找指定的文件
QDirIterator iter(dir,QDirIterator::Subdirectories);
while (iter.hasNext())
{
iter.next();
QFileInfo info=iter.fileInfo();
if (info.isFile())
{
return info.absoluteFilePath();
}
}
return "";
}
bool ThreadSendPro::SendFileHead(QString fileName,QString strRelativePath)
{
QFileInfo fileinfo;
fileinfo = QFileInfo(fileName);
// name:"xxxx",size:23434545,path:"/"
QJsonObject jsonFileInfo;
jsonFileInfo.insert("_type", "fileStart");
QString strOnlyFileName=fileinfo.fileName();
QString strExcName=fileinfo.suffix();
if(strExcName.isEmpty())
jsonFileInfo.insert("id", strOnlyFileName.left(strOnlyFileName.length()-strExcName.length()));
else
jsonFileInfo.insert("id", strOnlyFileName.left(strOnlyFileName.length()-strExcName.length()-1));
jsonFileInfo.insert("size", fileinfo.size());
//jsonFileInfo.insert("relative_path", strRelativePath);
jsonFileInfo.insert("relative_path", "");
jsonFileInfo.insert("zVer","xixun1");
QJsonDocument doc;
doc.setObject(jsonFileInfo);
QByteArray sendArray = doc.toJson(QJsonDocument::Compact);
QJsonObject jsonFileInfo1;
jsonFileInfo1.insert("_type", "jsonlen");
jsonFileInfo1.insert("jsonlen", sendArray.length());
QJsonDocument doc1;
doc1.setObject(jsonFileInfo1);
QByteArray sendArray1 = doc1.toJson(QJsonDocument::Compact);
if(bSendCloseFlag)
return false;
send->write(sendArray);
SynchronousSocketWrite();
return true;
}
bool ThreadSendPro::SendFileEnd(QString fileName)
{
QFileInfo fileinfo;
fileinfo = QFileInfo(fileName);
// name:"xxxx",size:23434545,path:"/"
QJsonObject jsonFileInfo;
jsonFileInfo.insert("_type", "fileEnd");
QString strOnlyFileName=fileinfo.fileName();
QString strExcName=fileinfo.suffix();
if(strExcName.isEmpty())
jsonFileInfo.insert("id", strOnlyFileName.left(strOnlyFileName.length()-strExcName.length()));
else {
jsonFileInfo.insert("id", strOnlyFileName.left(strOnlyFileName.length()-strExcName.length()-1));
}
jsonFileInfo.insert("zVer","xixun1");
QJsonDocument doc;
doc.setObject(jsonFileInfo);
QByteArray sendArray = doc.toJson(QJsonDocument::Compact);
if(bSendCloseFlag)
return false;
send->write(sendArray);
SynchronousSocketWrite();
return true;
}
bool ThreadSendPro::SendFileData(QString fileName)
{
qint64 llSendBytes=0;
file = new QFile(fileName);
// QFileInfo ff(fileName);
// QString sss=ff.fileName().left(ff.fileName().length()-ff.suffix().length()-1);
// QFile *fileNew = new QFile(ff.absolutePath()+"/"+sss+"copy."+ff.suffix());
// if(!fileNew->open(QFile::WriteOnly)) // 打开失败
// {
// }
if(!file->open(QFile::ReadOnly))
{
emit sigSetLableText(tr("open file failed"));
//emit sigSetLableText(fileName);
//qDebug() << "*** start_transfer(): File-Open-Error";
return false;
}
qint64 llfileSize = file->size();
qint64 llrestBytes=llfileSize;
while (llSendBytes<llfileSize) {
QByteArray buf = file->read(qMin(loadBytes, llrestBytes));
//QJsonValue JsonData=QJsonDocument::fromJson(buf).toVariant().toJsonValue();
//QJsonObject json_object2 = QJsonDocument::fromJson(buf).object();
/* 发送 */
// QString strData;
// strData.prepend(buf);
// QFileInfo fileinfo;
// fileinfo = QFileInfo(fileName);
// QJsonObject jsonFileInfo;
// jsonFileInfo.insert("_type", "fileData");
// jsonFileInfo.insert("name", fileinfo.fileName());
// jsonFileInfo.insert("data", buf);
// jsonFileInfo.insert("zVer","xixun1");
// QJsonDocument doc;
// doc.setObject(jsonFileInfo);
// QByteArray sendArray = doc.toJson(QJsonDocument::Compact);
if(bSendCloseFlag)
{
file->close();
return false;
}
qint64 iSendResultLength=send->write(buf);
// send->waitForBytesWritten();
// fileNew->write(buf);
llSendBytes+=iSendResultLength ;
llrestBytes=llfileSize-llSendBytes;
sentAllBytes += iSendResultLength;
if(sentAllBytes!=0)
emit sigSetProgressValue(sentAllBytes);
SynchronousSocketWrite();
}
file->close();
// fileNew->close();
return true;
}
/*--- 出错处理 ---*/
void ThreadSendPro::show_error(QAbstractSocket::SocketError error)
{
//qDebug() << "*** Socket Error";
QString strTip=QString::number(error);
if(error!=6)
{
//send->close();
bSendCloseFlag=true;
// emit sigSetLableText(tr("send failed")+strTip);
emit sigSetLableText(strTip);
//emit sigSetProgressValue(0); // 进度条归零
m_reSendCount=0;
}
// emit sigSetLableText("连接失败");
}
bool ThreadSendPro::SynchronousSocketWrite()
{
if(bSendCloseFlag)
return false;
if(!send->waitForBytesWritten(3000))
{
qDebug()<<"socket write timeout!";
return false;
}
//readAckSempahore.acquire();
return true;
}
void ThreadSendPro::recevie_file()
{
//QDataStream in(receive);
//in.setVersion(DATA_STREAM_VERSION);
//QFile *tempFile=nullptr;
//receive->bytesAvailable();
// if(send->waitForReadyRead())
{
//QByteArray readBuf=send->readAll();
QByteArray readBuf=send->read(send->bytesAvailable());
QJsonParseError parseJsonErr;
QJsonDocument document = QJsonDocument::fromJson(readBuf,&parseJsonErr);
if(!(parseJsonErr.error == QJsonParseError::NoError))
{
//qDebug()<<tr("解析json文件错误");
//return;
}
QJsonObject jsonObject = document.object();
QString strType=jsonObject["_type"].toString();
if(strType=="AckSuccess")
{
//释放信号
readAckSempahore.release();
}
else if(strType=="consult"){
m_NeedSendFileList.clear();
QJsonArray bb=jsonObject["idList"].toArray();
for(int i=0;i<bb.count();i++)
m_NeedSendFileList.append(bb.at(i).toString());
m_bGetConsultAckFlag=true;
readAckSempahore.release();
}
}
}