基于QT实现文件上传和下载功能

本文实例为大家分享了基于QT实现文件上传和下载的具体代码,供大家参考,具体内容如下

功能

支持文件上传功能

支持文件下载功能

支持断点续传功能

支持连续多个文件的上传下载

文件上传下载流程

在确认断点的时候会利用md5进行数据校验,防止数据发生更改。

服务端

采用多线程的Reactor模式。即一个线程对应多个filesocket进行文件上传下载。线程个数可设置,默认为1.

FileServer 继承QTcpServer,实现incomingConnection虚函数。当有新的连接到来时,会创建FileSocket并采用moveToThread接口,将其移入到当前活跃socket数量最少的线程中。

FileSocket采用Qt本身的事件循环和信号槽机制进行数据传输。通过设置两者的交互机制,避免了tcp的粘包问题以及QTcpSocket的readyRead信号触发问题。

服务端代码:

//fileserver.h #ifndef FILESERVER_H #define FILESERVER_H #include <QObject> #include <QTcpServer> #include <QAbstractSocket> #include <QTcpSocket> #include <QMap> #include <QString> #include <QThread> class FileServer : public QTcpServer {     Q_OBJECT public:     explicit FileServer(QString param_server_name,quint8 param_thread_count=1,QObject *parent = nullptr);     ~FileServer();     QString getServername() {return m_server_name;}     quint8 getThreadCount() {return m_thread_count;}     //获取当前每个线程的活跃socket数量     void threadMonitor(QMap<qint32,quint32>& param_info); signals: public slots:     //开始监听     bool run(quint16 port);     void socketClose(qint32 id); protected:     void incomingConnection(qintptr socketDescriptor);     struct ThreadInfo //线程信息,包括标志线程的ID和活跃socket的数量     {         qint32 id;         QThread msg_thread;         quint32 active_count;     };     //获取活跃socket数量最小的线程id     qint32 getMinActiveThread(); private:     QString m_server_name;     quint8 m_thread_count;     ThreadInfo* m_socket_thread; }; //fileserver.cpp #include "fileserver.h" #include "filesocket.h" #include <QTcpSocket> #include <QHostAddress> FileServer::FileServer(QString param_server_name,quint8 param_thread_count,QObject *parent) :     QTcpServer(parent),     m_server_name(param_server_name),     m_thread_count(param_thread_count) {     //根据用户给定的线程个数进行线程信息数组的申请,并进行初始化     this->m_socket_thread=new ThreadInfo[this->m_thread_count];     for(qint32 index=0;index<this->m_thread_count;index++)     {         this->m_socket_thread[index].id=index;         this->m_socket_thread[index].active_count=0;         //启动线程         this->m_socket_thread[index].msg_thread.start();     } } FileServer::~FileServer() {     if(this->isListening())     {         this->close();     }     //释放申请的线程信息数组     delete [] this->m_socket_thread;     this->m_socket_thread=nullptr; } void FileServer::threadMonitor(QMap<qint32, quint32>& param_info) {     for(qint32 index=0;index<this->m_thread_count;index++)     {         param_info[index]=this->m_socket_thread[index].active_count;     } } bool FileServer::run(quint16 port) {     if(this->isListening())     {         qDebug()<<"port("<<port<<")already listen,please close first."<<endl;         return true;     }     if(this->listen(QHostAddress::Any,port))     {         qDebug()<<"listen "<<this->m_server_name<<"port("<<port<<") successful."<<endl;         return true;     }     else     {         qDebug()<<"listen "<<"port("<<port<<") failed,please check the network port."<<endl;         return false;     } } void FileServer::socketClose(qint32 id) {     //槽函数,socket关闭的时候,将对应的线程的活跃socket数量减一     this->m_socket_thread[id].active_count--; } void FileServer::incomingConnection(qintptr socketDescriptor) {     qDebug()<<"new client connection:"<<socketDescriptor<<endl;     qint32 thread_id=this->getMinActiveThread();     //建立新的socket     FileSocket* new_socket=new FileSocket(this->m_socket_thread[thread_id].id,socketDescriptor);     connect(new_socket,SIGNAL(socketClose(qint32)),this,SLOT(socketClose(qint32)));     //移入到线程中运行     new_socket->moveToThread(&(this->m_socket_thread[thread_id].msg_thread));     this->m_socket_thread[thread_id].active_count++; } qint32 FileServer::getMinActiveThread() {     qint32 min_id=0;     for(qint32 index=1;index<this->m_thread_count;index++)     {         if(this->m_socket_thread[min_id].active_count>this->m_socket_thread[index].active_count)         {             min_id=index;         }     }     return min_id; } #endif // FILESERVER_H

filesocket

//filesocket.h #ifndef FILESOCKET_H #define FILESOCKET_H #include <QObject> #include <QAbstractSocket> #include <QTcpSocket> #include <QByteArray> #include <QFile> //文件上传下载的字段定义 #define FILE_UPLOAD_HEADER             100 #define FILE_UPLOAD_POS                101 #define FILE_UPLOAD_TAIL               103 #define FILE_DOWNLOAD_HEADER           200 #define FILE_DOWNLOAD_CONTENT          202 #define FILE_DOWNLOAD_TAIL             203 //错误码定义 #define OK                             0 #define FILE_WRITE_ERROR               -1 #define FILE_OPEN_ERROR                -2 #define FILE_SEEK_ERROR                -3 #define FILE_ALREADY_EXISTS_ERROR      -4 #define RECV_DATA_TIMEOUT_ERROR        -5 #define RECV_UNKNOW_DATA_ERROR         -6 #define CONNECT_SERVER_ERROR           -7 #define UPLOAD_FILE_ERROR              -8 #define DOWNLOAD_FILE_ERROR            -10 class FileSocket : public QObject {     Q_OBJECT public:     explicit FileSocket(qint32 param_id,qintptr param_socketDescriptor,QObject *parent = nullptr);     ~FileSocket(); signals:     void socketClose(qint32); //当socket关闭的时候,向FileServer发送关闭信号 public slots:     void socketError(QAbstractSocket::SocketError param_error);     void socketDisconnect();     //绑定readyRead信号,进行数据读取     void fileRead();     //文件数据处理     void fileHandle(qint64 param_request_id,QMap<QString,QVariant>& param_qst_file,QMap<QString,QVariant>& param_rst_file,bool& reply); protected:     void paramInit();     qint64 fileUploadHeader(QString filename,qint64& pos,QString& md5_value);     qint64 fileUploadPos(qint64 file_pos);     qint64 fileDownloadHeader(QString filename,qint64& pos,QString& md5_value,qint64& file_size);     qint64 fileDownloadContent(); private:     qint32 m_id;     QTcpSocket m_socket;     qint64 m_fileupload_state; //文件上传中间状态标志,分为头尾处理状态和文件数据传输状态。     qint64 m_file_totalBytes;     qint64 m_file_pos;     qint64 m_req_id;     QByteArray m_msgBytes;     QFile m_local_file;     qint64 m_status; }; #endif // FILESOCKET_H //filecosket.cpp #include "filesocket.h" #include <QDataStream> #include <QByteArray> #include <QMap> #include <QVariant> #include <QString> #include <QCryptographicHash> const QString g_root_dir="."; FileSocket::FileSocket(qint32 param_id,qintptr param_socketDescriptor,QObject *parent) :     QObject(parent),     m_id(param_id),     m_socket(this),     m_fileupload_state(0),     m_local_file(this) {     this->m_msgBytes.resize(0);     this->paramInit();     this->m_socket.setSocketDescriptor(param_socketDescriptor);     connect(&(this->m_socket),SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(socketError(QAbstractSocket::SocketError)));     //绑定readyRead信号,进行数据读取     connect(&(this->m_socket),SIGNAL(readyRead()),this,SLOT(fileRead())); } FileSocket::~FileSocket() { } void FileSocket::socketError(QAbstractSocket::SocketError param_error) {     qDebug()<<"socket error("<<param_error<<"): "<<this->m_socket.errorString()<<endl;     this->m_fileupload_state=0;     this->socketDisconnect(); } void FileSocket::socketDisconnect() {     this->m_socket.disconnectFromHost();     emit socketClose(this->m_id);     this->deleteLater(); } void FileSocket::fileRead() {     this->m_msgBytes.resize(0);     this->m_msgBytes=this->m_socket.readAll();     if(this->m_fileupload_state==0)     {         QDataStream file_in(&this->m_msgBytes,QIODevice::ReadOnly);         QMap<QString,QVariant> param_qst_file;         file_in>>this->m_req_id>>param_qst_file;         QByteArray paramBytes;         bool reply=true;         QMap<QString,QVariant> param_rst_file;         this->fileHandle(this->m_req_id,param_qst_file,param_rst_file,reply);         if(reply==true)         {             QDataStream msg_out(&paramBytes,QIODevice::WriteOnly);             msg_out<<qint64(this->m_req_id)<<param_rst_file;             this->m_socket.write(paramBytes);             this->m_socket.waitForBytesWritten();         }     }     else     {         //文件上传的时候,开始数据写入         this->m_file_totalBytes-=this->m_msgBytes.size();         if(this->m_status!=OK)         {             return;         }         qint64 wrtieBytes=this->m_local_file.write(this->m_msgBytes);         if(wrtieBytes==-1)         {             qDebug()<<"file write error"<<endl;             this->m_status=FILE_WRITE_ERROR;             return;         }         if(this->m_file_totalBytes==0)         {             this->m_local_file.close();             QByteArray paramBytes;             QMap<QString,QVariant> param_rst_file;             param_rst_file[QString("reply_status")]=QVariant(this->m_status);             QDataStream msg_out(&paramBytes,QIODevice::WriteOnly);             msg_out<<qint64(FILE_UPLOAD_TAIL)<<param_rst_file;             this->m_socket.write(paramBytes);             this->m_socket.waitForBytesWritten();             this->m_fileupload_state=0;         }     } } void FileSocket::fileHandle(qint64 param_request_id,QMap<QString,QVariant>& param_qst_file,QMap<QString,QVariant>& param_rst_file,bool& reply) {     switch (param_request_id)     {     case FILE_UPLOAD_HEADER:{         this->paramInit();         QString file_prjpath=param_qst_file[QString("file_prjpath")].toString();         qint64 pos=0;         QString md5_value;         qint64 status=this->fileUploadHeader(file_prjpath,pos,md5_value);         if(status==OK)         {             this->m_fileupload_state=0;         }         param_rst_file[QString("reply_status")]=QVariant(status);         param_rst_file[QString("file_pos")]=QVariant(pos);         param_rst_file[QString("file_md5")]=QVariant(md5_value);         break;     }     case FILE_UPLOAD_POS:{         qint64 file_pos=param_qst_file[QString("file_pos")].toInt();         this->m_file_totalBytes=param_qst_file[QString("file_size")].toInt();         qint64 status=this->fileUploadPos(file_pos);         if(status==OK)         {             this->m_fileupload_state=1;         }         param_rst_file[QString("reply_status")]=QVariant(status);         break;     }     case FILE_DOWNLOAD_HEADER:{         this->paramInit();         QString file_prjpath=param_qst_file[QString("file_prjpath")].toString();         this->m_file_pos=param_qst_file[QString("file_pos")].toInt();         QString file_md5_value=param_qst_file[QString("file_md5")].toString();         qint64 status=this->fileDownloadHeader(file_prjpath,this->m_file_pos,file_md5_value,this->m_file_totalBytes);         if(status==OK)         {             this->m_fileupload_state=0;         }         param_rst_file[QString("reply_status")]=QVariant(status);         param_rst_file[QString("file_pos")]=QVariant(this->m_file_pos);         param_rst_file[QString("file_size")]=QVariant(this->m_file_totalBytes);         break;     }     case FILE_DOWNLOAD_CONTENT:{         reply=false;         this->fileDownloadContent();         break;     }     case FILE_DOWNLOAD_TAIL:{         qint64 status=OK;         this->m_fileupload_state=0;         param_rst_file[QString("reply_status")]=QVariant(status);         break;     }     } } void FileSocket::paramInit() {     this->m_file_totalBytes=0;     this->m_status=OK;     this->m_file_pos=0; } qint64 FileSocket::fileUploadHeader(QString filename, qint64 &pos, QString &md5_value) {     QString filepath=QString("%1/%2").arg(g_root_dir).arg(filename);     this->m_local_file.setFileName(filepath);     if(this->m_local_file.exists()==false)     {         pos=0;         return OK;     }     else     {         pos=this->m_local_file.size();         if(pos==0)         {             return OK;         }         if(this->m_local_file.open(QIODevice::ReadOnly)==false)         {              pos=0;              qDebug()<<"open file("<<this->m_local_file.fileName()<<") failed."<<endl;              return FILE_OPEN_ERROR;         }         QCryptographicHash file_md5(QCryptographicHash::Md5);         qint64 payloadSize=10*1024*1024;         QByteArray file_data=this->m_local_file.read(payloadSize);         while(!file_data.isEmpty())         {             file_md5.addData(file_data);             file_data=this->m_local_file.read(payloadSize);         }         this->m_local_file.close();         md5_value=QString(file_md5.result().toHex());         return OK;     } } qint64 FileSocket::fileUploadPos(qint64 file_pos) {     if(this->m_local_file.open(QIODevice::WriteOnly)==false)     {         qDebug()<<"open file("<<this->m_local_file.fileName()<<") failed."<<endl;         return FILE_OPEN_ERROR;     }     if(this->m_local_file.seek(file_pos)==false)     {         qDebug()<<"seek file("<<this->m_local_file.fileName()<<") failed."<<endl;         this->m_local_file.close();         return FILE_SEEK_ERROR;     }     return OK; } qint64 FileSocket::fileDownloadHeader(QString filename, qint64 &pos, QString &md5_value, qint64 &file_size) {     this->m_local_file.setFileName(QString("%1/%2").arg(g_root_dir).arg(filename));     if(this->m_local_file.open(QIODevice::ReadOnly)==false)     {         qDebug()<<"file open error"<<endl;         return FILE_OPEN_ERROR;     }     file_size=this->m_local_file.size();     if(pos==0)     {         this->m_local_file.close();         return OK;     }     QCryptographicHash file_md5(QCryptographicHash::Md5);     qint64 payloadSize=10*1024*1024;     qint64 file_pos=pos;     qint64 readBytes=0;     while(file_pos>0)     {         readBytes=qMin(file_pos,payloadSize);         QByteArray file_data=this->m_local_file.read(readBytes);         file_md5.addData(file_data);         file_pos-=readBytes;     }     this->m_local_file.close();     if(QString(file_md5.result().toHex())!=md5_value)     {         pos=0;     }     file_size-=pos;     return OK; } qint64 FileSocket::fileDownloadContent() {     if(this->m_local_file.open(QIODevice::ReadOnly)==false)     {         qDebug()<<"file open error"<<endl;         return FILE_OPEN_ERROR;     }     this->m_local_file.seek(this->m_file_pos);     qint64 payloadSize=1*1024*1024;     while(this->m_file_totalBytes!=0)     {         QByteArray readData=this->m_local_file.read(qMin(this->m_file_totalBytes,payloadSize));         this->m_file_totalBytes-=this->m_socket.write(readData);         this->m_socket.waitForBytesWritten();     }     return OK; } 客户端

即支持单个文件和文件列表的上传和下载,一个socket可连续进行文件的上传和下载。

客户端源码

//fileclient.h #ifndef FILECLIENT_H #define FILECLIENT_H #include <QObject> #include <QAbstractSocket> #include <QTcpSocket> #include <QByteArray> #include <QString> #include <QStringList> #include <QFile> //文件上传下载字段定义 #define FILE_UPLOAD_HEADER             100 #define FILE_UPLOAD_POS                101 #define FILE_UPLOAD_TAIL               103 #define FILE_DOWNLOAD_HEADER           200 #define FILE_DOWNLOAD_CONTENT          202 #define FILE_DOWNLOAD_TAIL             203 //错误码定义 #define OK                             0 #define FILE_WRITE_ERROR               -1 #define FILE_OPEN_ERROR                -2 #define FILE_SEEK_ERROR                -3 #define FILE_ALREADY_EXISTS_ERROR      -4 #define RECV_DATA_TIMEOUT_ERROR        -5 #define RECV_UNKNOW_DATA_ERROR         -6 #define CONNECT_SERVER_ERROR           -7 #define UPLOAD_FILE_ERROR              -8 #define DOWNLOAD_FILE_ERROR            -10 class FileClient : public QObject {     Q_OBJECT public:     explicit FileClient(QString ip,quint16 port,QObject *parent = nullptr);     ~FileClient(); public slots:     qint64 filesUpload(QStringList filepath_list);     qint64 fileUpload(QString filepath);     qint64 filesDownload(QStringList filepath_list);     qint64 fileDownload(QString filepath); protected:     qint64 fileUploadHeader(QString filepath);     qint64 fileUploadPos();     qint64 fileUploadContent();     qint64 fileUploadTail();     qint64 fileDownloadHeader(QString filepath);     qint64 fileDownloadContent();     qint64 fileDownloadTail();     qint64 fileUploadRecvData(qint64 req_id,QMap<QString, QVariant>& recv_data);     bool socketConnect();     void paramInit();     qint64 file_clc_md5(QString &md5_value); private:     QString m_ip;     quint16 m_port;     qint64 m_file_pos;     qint64 m_payloadSize;     qint64 m_file_total_size;     QFile m_local_file;     QTcpSocket m_socket; }; #endif // FILECLIENT_H //fileclient.cpp #include "fileclient.h" #include <QDataStream> #include <QHostAddress> #include <QFile> #include <QCryptographicHash> #include <QVariant> #include <QFile> #include <QFileInfo> FileClient::FileClient(QString ip,quint16 port,QObject *parent) :     QObject(parent),     m_ip(ip),     m_port(port),     m_socket(this) { } FileClient::~FileClient() {     if(this->m_socket.isOpen())     {         this->m_socket.close();     } } qint64 FileClient::filesUpload(QStringList filepath_list) {     qint64 status=OK;     foreach (QString filepath, filepath_list)     {         status=this->fileUpload(filepath);         if(status!=OK)         {             return status;         }     }     return status; } qint64 FileClient::fileUpload(QString filepath) {     qint64 status=OK;     this->paramInit();     status=this->fileUploadHeader(filepath);     if(status==FILE_ALREADY_EXISTS_ERROR) //already exist     {         return OK;     }     else if(status!=OK)     {         this->m_socket.disconnectFromHost();         return status;     }     status=this->fileUploadPos();     if(status!=OK)     {         this->m_socket.disconnectFromHost();         return status;     }     status=this->fileUploadContent();     if(status!=OK)     {         this->m_socket.disconnectFromHost();         return status;     }     status=this->fileUploadTail();     if(status!=OK)     {         this->m_socket.disconnectFromHost();         return status;     }     return status; } qint64 FileClient::filesDownload(QStringList filepath_list) {     qint64 status=OK;     foreach (QString filepath, filepath_list)     {         status=this->fileDownload(filepath);         if(status!=OK)         {             return status;         }     }     return status; } qint64 FileClient::fileDownload(QString filepath) {     qint64 status=OK;     this->paramInit();     status=this->fileDownloadHeader(filepath);     if(status==FILE_ALREADY_EXISTS_ERROR) //already exists     {         return OK;     }     else if(status!=OK)     {         this->m_socket.disconnectFromHost();         return status;     }     status=this->fileDownloadContent();     if(status!=OK)     {         this->m_socket.disconnectFromHost();         return status;     }     status=this->fileDownloadTail();     if(status!=OK)     {         this->m_socket.disconnectFromHost();         return status;     }     return status; } qint64 FileClient::fileUploadRecvData(qint64 req_id, QMap<QString, QVariant>& recv_data) {     if(this->m_socket.waitForReadyRead()==false)     {         return RECV_DATA_TIMEOUT_ERROR;     }     qint64 recv_rsp_id=OK;     QByteArray inblock=this->m_socket.readAll();     QDataStream rsp_in(&inblock,QIODevice::ReadOnly);     rsp_in>>recv_rsp_id>>recv_data;     if(req_id!=recv_rsp_id)     {         return RECV_UNKNOW_DATA_ERROR;     }     return qint64(recv_data[QString("reply_status")].toInt()); } qint64 FileClient::fileUploadHeader(QString filepath) {     if(this->m_socket.isOpen()==false)     {         if(this->socketConnect()==false)         {             qDebug()<<"socket connect failed:"<<this->m_socket.errorString()<<endl;             return CONNECT_SERVER_ERROR;         }     }     this->m_local_file.setFileName(filepath);     if(this->m_local_file.open(QIODevice::ReadOnly)==false)     {         qDebug()<<"read file failed:"<<this->m_local_file.errorString()<<endl;         return FILE_OPEN_ERROR;     }     this->m_file_total_size=this->m_local_file.size();     this->m_local_file.close();     QByteArray outblock;     QDataStream file_out(&outblock,QIODevice::WriteOnly);     QMap<QString,QVariant> file_header;     file_header[QString("file_prjpath")]=QVariant(filepath.right(filepath.size()-filepath.lastIndexOf('/')-1));     file_out<<qint64(FILE_UPLOAD_HEADER)<<file_header;     this->m_socket.write(outblock);     this->m_socket.waitForBytesWritten();     QMap<QString, QVariant> rsp_msg;     qint64 recv_status=this->fileUploadRecvData(FILE_UPLOAD_HEADER,rsp_msg);     if(recv_status!=OK)     {         return recv_status;     }     this->m_file_pos=rsp_msg[QString("file_pos")].toInt();     QString recv_md5=rsp_msg[QString("file_md5")].toString();     if(this->m_file_pos==0)     {         return OK;     }     else     {         if(this->m_local_file.open(QIODevice::ReadOnly)==false)         {             return FILE_OPEN_ERROR;         }         qint64 readtotalBytes=0;         qint64 payloadSize=10*1024*1024;         QCryptographicHash clc_md5(QCryptographicHash::Md5);         while(readtotalBytes<this->m_file_pos)         {             qint64 readBytes=qMin(payloadSize,this->m_file_pos-readtotalBytes);             clc_md5.addData(this->m_local_file.read(readBytes));             readtotalBytes+=readBytes;         }         this->m_local_file.close();         if(QString(clc_md5.result().toHex())!=recv_md5)         {             this->m_file_pos=0;         }         this->m_file_total_size-=this->m_file_pos;         if(this->m_file_total_size==0)         {             return FILE_ALREADY_EXISTS_ERROR;         }         else         {             return OK;         }     } } qint64 FileClient::fileUploadPos() {     QByteArray outblock;     QDataStream file_out(&outblock,QIODevice::WriteOnly);     QMap<QString,QVariant> file_header;     file_header[QString("file_pos")]=QVariant(this->m_file_pos);     file_header[QString("file_size")]=QVariant(this->m_file_total_size);     file_out<<qint64(FILE_UPLOAD_POS)<<file_header;     this->m_socket.write(outblock);     this->m_socket.waitForBytesWritten();     QMap<QString, QVariant> rsp_msg;     qint64 recv_status=this->fileUploadRecvData(FILE_UPLOAD_POS,rsp_msg);     return recv_status; } qint64 FileClient::fileUploadContent() {     if(this->m_socket.isOpen()==false)     {         return CONNECT_SERVER_ERROR;     }     if(this->m_local_file.open(QIODevice::ReadOnly)==false)     {         return FILE_OPEN_ERROR;     }     this->m_local_file.seek(this->m_file_pos);     while(this->m_file_total_size!=0)     {         this->m_file_total_size-=this->m_socket.write(this->m_local_file.read(qMin(this->m_file_total_size,this->m_payloadSize)));         this->m_socket.waitForBytesWritten();     }     return OK; } qint64 FileClient::fileUploadTail() {     if(this->m_socket.isOpen()==false)     {         return CONNECT_SERVER_ERROR;     }     QMap<QString, QVariant> rsp_msg;     qint64 recv_status=this->fileUploadRecvData(FILE_UPLOAD_TAIL,rsp_msg);     return recv_status; } qint64 FileClient::fileDownloadHeader(QString filepath) {     if(this->m_socket.isOpen()==false)     {         if(this->socketConnect()==false)         {             qDebug()<<"connect server error"<<endl;             return CONNECT_SERVER_ERROR;         }     }     qint64 file_pos=0;     QString file_md5_value;     this->m_local_file.setFileName(filepath);     if(this->m_local_file.open(QIODevice::ReadOnly)==false)     {         file_pos=0;     }     else     {         file_pos=this->m_local_file.size();         qint64 readtotalBytes=0;         qint64 payloadSize=10*1024*1024;         QCryptographicHash clc_md5(QCryptographicHash::Md5);         while(readtotalBytes<file_pos)         {             qint64 readBytes=qMin(payloadSize,file_pos-readtotalBytes);             clc_md5.addData(this->m_local_file.read(readBytes));             readtotalBytes+=readBytes;         }         file_md5_value=QString(clc_md5.result().toHex());         this->m_local_file.close();     }     QByteArray outblock;     QDataStream file_out(&outblock,QIODevice::WriteOnly);     QMap<QString,QVariant> file_header;     file_header[QString("file_prjpath")]=QVariant(filepath);     file_header[QString("file_pos")]=QVariant(file_pos);     file_header[QString("file_md5")]=QVariant(file_md5_value);     file_out<<qint64(FILE_DOWNLOAD_HEADER)<<file_header;     this->m_socket.write(outblock);     this->m_socket.waitForBytesWritten();     QMap<QString, QVariant> rsp_msg;     qint64 recv_status=this->fileUploadRecvData(FILE_DOWNLOAD_HEADER,rsp_msg);     if(recv_status!=OK)     {         return recv_status;     }     this->m_file_pos=rsp_msg[QString("file_pos")].toInt();     this->m_file_total_size=rsp_msg[QString("file_size")].toInt();     if(0==this->m_file_total_size)     {         qDebug()<<"file already exist error"<<endl;         return FILE_ALREADY_EXISTS_ERROR;     }     QByteArray outblock2;     QDataStream file_out2(&outblock2,QIODevice::WriteOnly);     QMap<QString,QVariant> file_header2;     file_header2[QString("reply_status")]=QVariant(qint64(OK));     file_out2<<qint64(FILE_DOWNLOAD_CONTENT)<<file_header2;     this->m_socket.write(outblock2);     this->m_socket.waitForBytesWritten();     return OK; } qint64 FileClient::fileDownloadContent() {      if(this->m_local_file.open(QIODevice::WriteOnly)==false)     {         qDebug()<<"file open error:"<<this->m_local_file.fileName()<<endl;         return FILE_OPEN_ERROR;     }     this->m_local_file.seek(this->m_file_pos);     qint64 status=OK;     while(this->m_file_total_size>0)     {         if(this->m_socket.waitForReadyRead()==false)         {             status=RECV_DATA_TIMEOUT_ERROR;             break;         }         QByteArray inblock=this->m_socket.readAll();         this->m_file_total_size-=inblock.size();         if(status==OK)         {             if(this->m_local_file.write(inblock)==-1)             {                 status=FILE_WRITE_ERROR;             }         }     }     this->m_local_file.close();     if(status==OK)     {         QByteArray outblock2;         QDataStream file_out2(&outblock2,QIODevice::WriteOnly);         QMap<QString,QVariant> file_header2;         file_header2[QString("reply_status")]=QVariant(qint64(OK));         file_out2<<qint64(FILE_DOWNLOAD_TAIL)<<file_header2;         this->m_socket.write(outblock2);         this->m_socket.waitForBytesWritten();     }     return status; } qint64 FileClient::fileDownloadTail() {     QMap<QString, QVariant> rsp_msg;     qint64 recv_status=this->fileUploadRecvData(FILE_DOWNLOAD_TAIL,rsp_msg);     return recv_status; } bool FileClient::socketConnect() {     this->m_socket.close();     this->m_socket.connectToHost(QHostAddress(this->m_ip),this->m_port);     if(this->m_socket.waitForConnected()==false)     {         qDebug()<<"connect timeout:"<<this->m_ip<<this->m_port<<endl;         return false;     }     return true; } void FileClient::paramInit() {     this->m_file_pos=0;     this->m_payloadSize=1*1024*1024;//1MB     this->m_local_file.close();     this->m_file_total_size=0; }

推荐阅读