本文小编为大家详细介绍“怎么用QT实现文件传输功能”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么用QT实现文件传输功能”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
过程如下:
1、服务器端设置监听套接字,开始监听;
2、客户端在连接成功时开始传送文件,有connected()信号连接send()槽,send()发送文件头信息,包括文件名、文件总大小和文件名大小等;
3、传送完文件头信息时开始传送文件内容,有bytesWritten(qint64)信号连接到goOnSend(qint64)槽,前者是当想套接字写入数据时会出发的信号,即当已经想套接字写入数据,就继续传送数据,有send()传送文件头信息开始触发,直到文件传完为止。
4、在服务器端,首先接收文件头信息,然后读取文件名来用新建文件的方式打开一个文件,然后读取文件名即文件等大小信息,用来更新进度条和继续接收数据;
5、实现循环传输,在客户端,因为第一次send()是由connected()信号触发的,之后的每次传送应该手动调用send();在服务器端,在有新数据到达时,会判断是否为头文件,因此在每次文件传完的时候将byteReceived重置为0,即下一次再接收到数据的时候依据byteReceived判断的结果就是一个新文件了。
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QTcpSocket> #include <QFile> #include <string> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; QTcpSocket *tcpClient; QFile *localFile; QString fileName; //文件名 QByteArray outBlock; //分次传 qint64 loadSize; //每次发送数据的大小 qint64 byteToWrite; //剩余数据大小 qint64 totalSize; //文件总大小 int sendTimes; //用来标记是否为第一次发送,第一次以后连接信号触发,后面的则手动调用 private slots: void send(); //传送文件头信息 void goOnSend(qint64); //传送文件内容 void on_openPushButton_clicked(); void on_sendPushButton_clicked(); }; #endif // WIDGET_H
widget.cpp
#include "widget.h" #include "ui_widget.h" #include <QHostAddress> #include <QTextCodec> #include <QFileDialog> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); ui->progressLabel->hide(); QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF8")); tcpClient = new QTcpSocket(this); sendTimes = 0; connect(tcpClient, SIGNAL(connected()), this, SLOT(send())); //当连接成功时,就开始传送文件 connect(tcpClient, SIGNAL(bytesWritten(qint64)), this, SLOT(goOnSend(qint64))); } void Widget::send() //发送文件头信息 { byteToWrite = localFile->size(); //剩余数据的大小 totalSize = localFile->size(); loadSize = 4*1024; //每次发送数据的大小 QDataStream out(&outBlock, QIODevice::WriteOnly); QString currentFileName = fileName.right(fileName.size() - fileName.lastIndexOf('/')-1); out<<qint64(0)<<qint64(0)<<currentFileName; totalSize += outBlock.size(); //总大小为文件大小加上文件名等信息大小 byteToWrite += outBlock.size(); out.device()->seek(0); //回到字节流起点来写好前面连个qint64,分别为总大小和文件名等信息大小 out<<totalSize<<qint64(outBlock.size()); tcpClient->write(outBlock); //将读到的文件发送到套接字 ui->progressLabel->show(); ui->sendProgressBar->setMaximum(totalSize); ui->sendProgressBar->setValue(totalSize - byteToWrite); } void Widget::goOnSend(qint64 numBytes) //开始发送文件内容 { byteToWrite -= numBytes; //剩余数据大小 outBlock = localFile->read(qMin(byteToWrite, loadSize)); tcpClient->write(outBlock); ui->sendProgressBar->setMaximum(totalSize); ui->sendProgressBar->setValue(totalSize - byteToWrite); if(byteToWrite == 0) //发送完毕 ui->sendStatusLabel->setText(tr("文件发送完毕!")); } Widget::~Widget() { delete ui; } void Widget::on_openPushButton_clicked() //打开文件并获取文件名(包括路径) { ui->sendStatusLabel->setText(tr("正在打开文件...")); ui->sendProgressBar->setValue(0); //非第一次发送 loadSize = 0; byteToWrite = 0; totalSize = 0; outBlock.clear(); fileName = QFileDialog::getOpenFileName(this); localFile = new QFile(fileName); localFile->open(QFile::ReadOnly); ui->sendStatusLabel->setText(tr("已打开文件 %1").arg(fileName)); } void Widget::on_sendPushButton_clicked() { if(sendTimes == 0) //只有第一次发送的时候,是发生在连接产生信号connect时 { tcpClient->connectToHost(QHostAddress("192.168.1.137"), 1000); sendTimes = 1; } else send(); //第一次发送的时候是由connectToHost出发connect信号才能调用send,第二次之后就需要调用send了 ui->sendStatusLabel->setText(tr("正在发送文件 %1").arg(fileName)); }
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QtNetwork/QTcpServer> #include <QtNetwork/QTcpSocket> #include <QFile> #include <QString> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; QTcpServer *server; QTcpSocket *receivedSocket; QFile *newFile; QByteArray inBlock; QString fileName; qint64 totalSize; //总共需要发送的文件大小(文件内容&文件名信息) qint64 byteReceived; //已经发送的大小 private slots: void acceptConnection(); void readClient(); void on_pushButton_clicked(); }; #endif // WIDGET_H
widget.cpp
#include "widget.h" #include "ui_widget.h" #include <QTextCodec> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); ui->progressLabel->hide(); QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF8")); } void Widget::acceptConnection() { ui->receivedStatusLabel->setText(tr("已连接,正在准备接收文件!")); receivedSocket = server->nextPendingConnection(); connect(receivedSocket, SIGNAL(readyRead()), this, SLOT(readClient())); } void Widget::readClient() { ui->receivedStatusLabel->setText(tr("正在接收文件...")); if(byteReceived == 0) //才刚开始接收数据,此数据为文件信息 { ui->receivedProgressBar->setValue(0); QDataStream in(receivedSocket); in>>totalSize>>byteReceived>>fileName; newFile = new QFile(fileName); newFile->open(QFile::WriteOnly); } else //正式读取文件内容 { inBlock = receivedSocket->readAll(); byteReceived += inBlock.size(); newFile->write(inBlock); newFile->flush(); } ui->progressLabel->show(); ui->receivedProgressBar->setMaximum(totalSize); ui->receivedProgressBar->setValue(byteReceived); if(byteReceived == totalSize) { ui->receivedStatusLabel->setText(tr("%1接收完成").arg(fileName)); inBlock.clear(); byteReceived = 0; totalSize = 0; } } Widget::~Widget() { delete ui; } void Widget::on_pushButton_clicked() { totalSize = 0; byteReceived = 0; server = new QTcpServer(this); server->listen(QHostAddress("192.168.1.137"), 1000); connect(server, SIGNAL(newConnection()), this, SLOT(acceptConnection())); ui->receivedProgressBar->setValue(0); ui->receivedStatusLabel->setText(tr("开始监听...")); }
读到这里,这篇“怎么用QT实现文件传输功能”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。