QT实现文件传输功能

 更新时间:2022年8月18日 19:20  点击:454 作者:我是黏黏虫

本文实例为大家分享了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("开始监听..."));  
} 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持猪先飞。

原文出处:https://blog.csdn.net/haiyangwuxian/article/details/77679167

[!--infotagslink--]

相关文章

  • Qt 使用Poppler实现pdf阅读器的示例代码

    下面小编就为大家分享一篇Qt 使用Poppler实现pdf阅读器的示例代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-25
  • 将matplotlib绘图嵌入pyqt的方法示例

    这篇文章主要介绍了将matplotlib绘图嵌入pyqt的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-27
  • Qt定时器和随机数详解

    在前一篇中我们介绍了键盘和鼠标事件,其实还有一个非常常用的事件,就是定时器事件,如果要对程序实现时间上的控制,那么就要使用到定时器。而随机数也是很常用的一个功能,在我们要想产生一个随机的结果时就要使用到随机数。本文我们就来简单介绍一下定时器和随机数。...2020-04-25
  • 一篇文章教你3分钟如何发布Qt程序

    这篇文章主要给大家介绍了关于教你3分钟如何发布Qt程序的相关资料,文中通过实例代码结束的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-08-24
  • Qt实现闹钟小程序

    这篇文章主要为大家详细介绍了Qt实现闹钟小程序,利用Qt的designer设计需要的闹钟界面,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
  • Qt使用windeployqt工具实现程序打包发布方法

    本文主要介绍了Qt使用windeployqt工具实现程序打包发布方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-11-01
  • 浅谈Qt信号与槽的各种连接方式

    信号和槽是Qt特有的信息传输机制,本文主要介绍了浅谈Qt信号与槽的各种连接方式,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-02
  • PyQt QMainWindow的使用示例

    这篇文章主要介绍了PyQt QMainWindow的使用示例,帮助大家更好的理解和学习使用pyqt,感兴趣的朋友可以了解下...2021-03-20
  • Qt实现UDP多线程数据处理及发送的简单实例

    本文主要介绍了Qt实现UDP多线程数据处理及发送的简单实例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-10-21
  • Qt自定义控件实现线条型加载条

    这篇文章主要为大家详细介绍了Qt自定义控件实现线条型加载条,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
  • Qt自定义控件实现圆圈加载进度条

    这篇文章主要为大家详细介绍了Qt自定义控件实现圆圈加载进度条,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
  • Qt实现Flappy Bird游戏

    这篇文章主要为大家详细介绍了Qt实现Flappy Bird游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
  • Qt使用QPainter绘制3D立方体

    这篇文章主要为大家详细介绍了Qt使用QPainter绘制3D立方体,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-21
  • Qt实现进程界面之间的鼠标焦点切换

    这篇文章主要为大家详细介绍了Qt实现进程界面之间的鼠标焦点切换,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-09-25
  • QT开发应用程序的欢迎界面实例

    下面小编就为大家带来一篇QT开发应用程序的欢迎界面实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-04-25
  • Qt实现网络聊天室的示例代码

    本文主要介绍了Qt实现网络聊天室,实现一个在线聊天室, 使用tcp对客户端和服务器端进行通讯。具有一定的参考价值,具有一定的参考价值,...2021-06-23
  • QT串口通信的实现方法

    如果用qt写程序作为上位机,然后通过和usb和下位机通信的时候,就需要用到qt中的串口通信了。本文介绍了QT串口通信的实现方法,感兴趣的小伙伴们可以参考一下...2021-05-20
  • Qt之ui在程序中的使用-多继承法介绍

    本文将介绍Qt之ui在程序中的使用-多继承法,需要的朋友可以参考...2020-04-25
  • QT网络编程UDP下C/S架构广播通信(实例讲解)

    下面小编就为大家带来一篇QT网络编程UDP下C/S架构广播通信(实例讲解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-04-25
  • Qt自定义表头实现过滤功能的方法

    这篇文章主要个给大家介绍了关于Qt自定义表头实现过滤功能的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Qt具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-04-25