您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“怎么用QT實現(xiàn)文件傳輸功能”,內(nèi)容詳細,步驟清晰,細節(jié)處理妥當,希望這篇“怎么用QT實現(xiàn)文件傳輸功能”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。
過程如下:
1、服務(wù)器端設(shè)置監(jiān)聽套接字,開始監(jiān)聽;
2、客戶端在連接成功時開始傳送文件,有connected()信號連接send()槽,send()發(fā)送文件頭信息,包括文件名、文件總大小和文件名大小等;
3、傳送完文件頭信息時開始傳送文件內(nèi)容,有bytesWritten(qint64)信號連接到goOnSend(qint64)槽,前者是當想套接字寫入數(shù)據(jù)時會出發(fā)的信號,即當已經(jīng)想套接字寫入數(shù)據(jù),就繼續(xù)傳送數(shù)據(jù),有send()傳送文件頭信息開始觸發(fā),直到文件傳完為止。
4、在服務(wù)器端,首先接收文件頭信息,然后讀取文件名來用新建文件的方式打開一個文件,然后讀取文件名即文件等大小信息,用來更新進度條和繼續(xù)接收數(shù)據(jù);
5、實現(xiàn)循環(huán)傳輸,在客戶端,因為第一次send()是由connected()信號觸發(fā)的,之后的每次傳送應(yīng)該手動調(diào)用send();在服務(wù)器端,在有新數(shù)據(jù)到達時,會判斷是否為頭文件,因此在每次文件傳完的時候?qū)yteReceived重置為0,即下一次再接收到數(shù)據(jù)的時候依據(jù)byteReceived判斷的結(jié)果就是一個新文件了。
#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; //每次發(fā)送數(shù)據(jù)的大小 qint64 byteToWrite; //剩余數(shù)據(jù)大小 qint64 totalSize; //文件總大小 int sendTimes; //用來標記是否為第一次發(fā)送,第一次以后連接信號觸發(fā),后面的則手動調(diào)用 private slots: void send(); //傳送文件頭信息 void goOnSend(qint64); //傳送文件內(nèi)容 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() //發(fā)送文件頭信息 { byteToWrite = localFile->size(); //剩余數(shù)據(jù)的大小 totalSize = localFile->size(); loadSize = 4*1024; //每次發(fā)送數(shù)據(jù)的大小 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); //回到字節(jié)流起點來寫好前面連個qint64,分別為總大小和文件名等信息大小 out<<totalSize<<qint64(outBlock.size()); tcpClient->write(outBlock); //將讀到的文件發(fā)送到套接字 ui->progressLabel->show(); ui->sendProgressBar->setMaximum(totalSize); ui->sendProgressBar->setValue(totalSize - byteToWrite); } void Widget::goOnSend(qint64 numBytes) //開始發(fā)送文件內(nèi)容 { byteToWrite -= numBytes; //剩余數(shù)據(jù)大小 outBlock = localFile->read(qMin(byteToWrite, loadSize)); tcpClient->write(outBlock); ui->sendProgressBar->setMaximum(totalSize); ui->sendProgressBar->setValue(totalSize - byteToWrite); if(byteToWrite == 0) //發(fā)送完畢 ui->sendStatusLabel->setText(tr("文件發(fā)送完畢!")); } Widget::~Widget() { delete ui; } void Widget::on_openPushButton_clicked() //打開文件并獲取文件名(包括路徑) { ui->sendStatusLabel->setText(tr("正在打開文件...")); ui->sendProgressBar->setValue(0); //非第一次發(fā)送 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) //只有第一次發(fā)送的時候,是發(fā)生在連接產(chǎn)生信號connect時 { tcpClient->connectToHost(QHostAddress("192.168.1.137"), 1000); sendTimes = 1; } else send(); //第一次發(fā)送的時候是由connectToHost出發(fā)connect信號才能調(diào)用send,第二次之后就需要調(diào)用send了 ui->sendStatusLabel->setText(tr("正在發(fā)送文件 %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; //總共需要發(fā)送的文件大小(文件內(nèi)容&文件名信息) qint64 byteReceived; //已經(jīng)發(fā)送的大小 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) //才剛開始接收數(shù)據(jù),此數(shù)據(jù)為文件信息 { ui->receivedProgressBar->setValue(0); QDataStream in(receivedSocket); in>>totalSize>>byteReceived>>fileName; newFile = new QFile(fileName); newFile->open(QFile::WriteOnly); } else //正式讀取文件內(nèi)容 { 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("開始監(jiān)聽...")); }
讀到這里,這篇“怎么用QT實現(xiàn)文件傳輸功能”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。