本文实例为大家分享了基于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(¶mBytes,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(¶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;
}
客户端
即支持单个文件和文件列表的上传和下载,一个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;
}