qt/LedOK/wProgramManager/threadsendpro.cpp
2022-01-04 18:11:48 +08:00

527 lines
15 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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();
}
}
}