基于QT實(shí)現(xiàn)文件上傳和下載功能
本文實(shí)例為大家分享了基于QT實(shí)現(xiàn)文件上傳和下載的具體代碼,供大家參考,具體內(nèi)容如下
功能
- 支持文件上傳功能
- 支持文件下載功能
- 支持?jǐn)帱c(diǎn)續(xù)傳功能
- 支持連續(xù)多個(gè)文件的上傳下載
文件上傳下載流程
在確認(rèn)斷點(diǎn)的時(shí)候會(huì)利用md5進(jìn)行數(shù)據(jù)校驗(yàn),防止數(shù)據(jù)發(fā)生更改。
服務(wù)端
- 采用多線程的Reactor模式。即一個(gè)線程對(duì)應(yīng)多個(gè)filesocket進(jìn)行文件上傳下載。線程個(gè)數(shù)可設(shè)置,默認(rèn)為1.
- FileServer 繼承QTcpServer,實(shí)現(xiàn)incomingConnection虛函數(shù)。當(dāng)有新的連接到來時(shí),會(huì)創(chuàng)建FileSocket并采用moveToThread接口,將其移入到當(dāng)前活躍socket數(shù)量最少的線程中。
- FileSocket采用Qt本身的事件循環(huán)和信號(hào)槽機(jī)制進(jìn)行數(shù)據(jù)傳輸。通過設(shè)置兩者的交互機(jī)制,避免了tcp的粘包問題以及QTcpSocket的readyRead信號(hào)觸發(fā)問題。
服務(wù)端代碼:
//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;} ? ? //獲取當(dāng)前每個(gè)線程的活躍socket數(shù)量 ? ? void threadMonitor(QMap<qint32,quint32>& param_info); signals: public slots: ?? ?//開始監(jiān)聽 ? ? bool run(quint16 port); ? ? void socketClose(qint32 id); protected: ? ? void incomingConnection(qintptr socketDescriptor); ? ? struct ThreadInfo //線程信息,包括標(biāo)志線程的ID和活躍socket的數(shù)量 ? ? { ? ? ? ? qint32 id; ? ? ? ? QThread msg_thread; ? ? ? ? quint32 active_count; ? ? }; ? ? //獲取活躍socket數(shù)量最小的線程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) { ?? ?//根據(jù)用戶給定的線程個(gè)數(shù)進(jìn)行線程信息數(shù)組的申請(qǐng),并進(jìn)行初始化 ? ? 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; ? ? ? ? //啟動(dòng)線程 ? ? ? ? this->m_socket_thread[index].msg_thread.start(); ? ? } } FileServer::~FileServer() { ? ? if(this->isListening()) ? ? { ? ? ? ? this->close(); ? ? } ?? ? ?? ?//釋放申請(qǐng)的線程信息數(shù)組 ? ? 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) { ?? ?//槽函數(shù),socket關(guān)閉的時(shí)候,將對(duì)應(yīng)的線程的活躍socket數(shù)量減一 ? ? 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))); ? ? //移入到線程中運(yùn)行 ? ? 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 //錯(cuò)誤碼定義 #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); //當(dāng)socket關(guān)閉的時(shí)候,向FileServer發(fā)送關(guān)閉信號(hào) public slots: ? ? void socketError(QAbstractSocket::SocketError param_error); ? ? void socketDisconnect(); ? ?? ? ? //綁定readyRead信號(hào),進(jìn)行數(shù)據(jù)讀取 ? ? void fileRead(); ? ?? ? ? //文件數(shù)據(jù)處理 ? ? 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; //文件上傳中間狀態(tài)標(biāo)志,分為頭尾處理狀態(tài)和文件數(shù)據(jù)傳輸狀態(tài)。 ? ? 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信號(hào),進(jìn)行數(shù)據(jù)讀取 ? ? 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(¶mBytes,QIODevice::WriteOnly); ? ? ? ? ? ? msg_out<<qint64(this->m_req_id)<<param_rst_file; ? ? ? ? ? ? this->m_socket.write(paramBytes); ? ? ? ? ? ? this->m_socket.waitForBytesWritten(); ? ? ? ? } ? ? } ? ? else ? ? { ? ? ?? ?//文件上傳的時(shí)候,開始數(shù)據(jù)寫入 ? ? ? ? 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(¶mBytes,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; }
客戶端
即支持單個(gè)文件和文件列表的上傳和下載,一個(gè)socket可連續(xù)進(jìn)行文件的上傳和下載。
客戶端源碼
//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 //錯(cuò)誤碼定義 #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; }
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++從匯編的視角審視對(duì)象的創(chuàng)建問題
這篇文章主要介紹了C++從匯編的視角看對(duì)象的創(chuàng)建,從匯編的視角來看,調(diào)用構(gòu)造器和調(diào)用 “返回對(duì)象” 的函數(shù)是一樣的,從匯編的角度來看,對(duì)象就是一堆數(shù)據(jù)的排列,比如說最普通的對(duì)象就是數(shù)據(jù)成員按照聲明順序直接排列,需要的朋友可以參考下2022-01-01詳解計(jì)數(shù)排序算法及C語言程序中的實(shí)現(xiàn)
技術(shù)排序算法與我們普通接觸的冒泡排序和快速排序等基于元素比較的算法不同,在編程中通過C語言的數(shù)組能夠清除地表達(dá)出來,這里我們就來詳解計(jì)數(shù)排序算法及C語言程序中的實(shí)現(xiàn)2016-07-07C++實(shí)現(xiàn)LeetCode(28.實(shí)現(xiàn)strStr()函數(shù))
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(28.實(shí)現(xiàn)strStr()函數(shù)),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07基于C++實(shí)現(xiàn)一個(gè)簡單的音樂系統(tǒng)
C++中的Beep 函數(shù)是一個(gè)發(fā)出嗡鳴聲的函數(shù),本文將利用這個(gè)函數(shù)實(shí)現(xiàn)制作一個(gè)簡單的聲音系統(tǒng)。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-12-12海量數(shù)據(jù)處理系列之:用C++實(shí)現(xiàn)Bitmap算法
本篇文章是對(duì)用C++實(shí)現(xiàn)Bitmap算法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05C++實(shí)現(xiàn)統(tǒng)計(jì)代碼運(yùn)行時(shí)間的示例詳解
這篇文章主要為大家詳細(xì)介紹了C++一個(gè)有趣的小項(xiàng)目——統(tǒng)計(jì)代碼運(yùn)行時(shí)間,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-05-05