昨天我们写了QT之TCP网络编程,今天就来看一下,在QT下的文件传输,这是在昨天所写代码的基础上添加上的。。
先看一下最终效果:
文件传输主要步骤:
服务器端:
1、打开服务器端的文件所在路径
QString filePath = QFileDialog::getOpenFileName(this,"选择文件","../");
2、打开文件
bool isOK = file.open(QIODevice::ReadOnly);
3、先发送文件头部信息
//先发送文件头信息 文件名##文件大小
QString head = QString("%1##%2").arg(fileName).arg(fileSize);
//发送头部信息
qint64 len = tcpSocket->write(head.toUtf8());
4、发送真是的文件数据
//往文件里读数据
len = file.read(buf,sizeof(buf));
//发送数据,读多少,发多少
len = tcpSocket->write(buf,len);
客户端:
1、建立连接后收到服务器文件数据的信号槽
connect(tcpSocket,&QTcpSocket::readyRead,[=](){});
2、解析头部信息
//解析头部信息,初始化
fileName = QString(buf).section("##",0,0);
fileSize = QString(buf).section("##",1,1).toInt();
3、打开文件
bool isOK = file.open(QIODevice::WriteOnly|QIODevice::Append);
4、读取文件信息
quint64 len = file.write(buf);
这里还是贴一下源码吧,虽然可以实现传输文件功能,由于在网络编程基础上修改的,里边还存在一些bug,有兴趣的同学可以修改一下,使其完美一些.
不要忘记在.pro文件中添加
QT += core gui network
serverwidget.h
#ifndef SERVERWIDGET_H
#define SERVERWIDGET_H
#include
#include //监听套接字
#include //通信套接字
#include
#include
QT_BEGIN_NAMESPACE
namespace Ui { class ServerWidget; }
QT_END_NAMESPACE
class ServerWidget : public QWidget
{
Q_OBJECT
public:
ServerWidget(QWidget *parent = nullptr);
~ServerWidget();
void sendData();//发送数据
private slots:
void on_ButtonSend_clicked();
void on_ButtonClose_clicked();
void on_ButtonFile_clicked();
void on_ButtonFileSend_clicked();
private:
Ui::ServerWidget *ui;
QTcpServer *tcpServer;//监听套接字
QTcpSocket *tcpSocket;//通信套接字
QFile file;//文件对象
QString fileName;//文件名称
quint64 fileSize;//文件大小
quint64 sendSize;//已经发送文件大小
QTimer timer;//定时器
};
#endif // SERVERWIDGET_H
serverwidget.cpp
#include "serverwidget.h"
#include "ui_serverwidget.h"
#include
#include
#include
#include
ServerWidget::ServerWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::ServerWidget)
{
ui->setupUi(this);
//初始化套接字
tcpServer = NULL;
tcpSocket = NULL;
//监听套接字,指定父对象自动回收空间
tcpServer = new QTcpServer(this);
//设定端口
tcpServer->listen(QHostAddress::Any,8888);
//新连接建立的信号槽
connect(tcpServer,&QTcpServer::newConnection,[=](){
//取出建立好连接的套接字
tcpSocket = tcpServer->nextPendingConnection();
//获取对方的ip和端口
QString ip = tcpSocket->peerAddress().toString();
qint16 port = tcpSocket->peerPort();
//将信息显示到UI
QString temp = QString("[%1:%2]: 连接成功").arg(ip).arg(port);
ui->textEditRead->setText(temp);
//连接建立后读取到数据的信号槽
connect(tcpSocket,&QTcpSocket::readyRead,[=](){
//从通信套接字取出内容
QByteArray array = tcpSocket->readAll();
//显示到UI
ui->textEditRead->append(array);
});
});
connect(&timer,&QTimer::timeout,[=](){
//关闭定时器
timer.stop();
//发送文件
sendData();
});
setWindowTitle("TCP服务器,端口:8888");
}
ServerWidget::~ServerWidget()
{
delete ui;
}
void ServerWidget::on_ButtonSend_clicked()
{
if(NULL == tcpSocket)
{
return;
}
//获取编辑区内容
QString str = ui->textEditWrite->toPlainText();
//给对方发数据
tcpSocket->write(str.toUtf8().data());
}
void ServerWidget::on_ButtonClose_clicked()
{
if(NULL == tcpSocket)
{
return;
}
//主动和客户端断开连接
tcpSocket->disconnectFromHost();
//关闭套接字
tcpSocket->close();
tcpSocket = NULL;
}
//选择要发送的文件
void ServerWidget::on_ButtonFile_clicked()
{
QString filePath = QFileDialog::getOpenFileName(this,"选择文件","../");
//若文件路径无效。则提示
if(filePath.isEmpty())
{
QMessageBox::information(this,"提示:",filePath+"文件路径无效");
return ;
}
fileName.clear();
fileSize=0;
sendSize=0;
//获取文件信息
QFileInfo info(filePath);
fileName = info.fileName();
fileSize = info.size();
//以只读方式打开
//指定文件的名称
file.setFileName(filePath);
//打开文件
bool isOK = file.open(QIODevice::ReadOnly);
if(!isOK)
{
QMessageBox::information(this,"提示:","只读方式打开文件失败");
return ;
}
//提示打开文件路径
ui->textEditRead->append(filePath);
}
void ServerWidget::on_ButtonFileSend_clicked()
{
//先发送文件头信息 文件名##文件大小
QString head = QString("%1##%2").arg(fileName).arg(fileSize);
//发送头部信息
qint64 len = tcpSocket->write(head.toUtf8());
//如果len>0,则头部信息发送成功
if(len>0)
{
//发送真正的文件信息,为防止tcp黏包信息,定时器需要延时
timer.start(20);
}
else
{
QMessageBox::information(this,"提示:","头部信息发送失败");
file.close();
return ;
}
}
void ServerWidget::sendData()
{
quint64 len = 0;
do
{
//每次发送数据的大小
char buf[1024] = {0};
len=0;
//往文件里读数据
len = file.read(buf,sizeof(buf));
//发送数据,读多少,发多少
len = tcpSocket->write(buf,len);
sendSize+=len;
}while(len>0);
}
main.cpp 就不贴了,默认的就好(可以自己修改)。
clientwidget.h
#ifndef CLIENTWIDGET_H
#define CLIENTWIDGET_H
#include
#include //通信套接字
#include
QT_BEGIN_NAMESPACE
namespace Ui { class ClientWidget; }
QT_END_NAMESPACE
class ClientWidget : public QWidget
{
Q_OBJECT
public:
ClientWidget(QWidget *parent = nullptr);
~ClientWidget();
private slots:
void on_buttonSend_clicked();
void on_buttonClose_clicked();
void on_ButtonConnect_clicked();
private:
Ui::ClientWidget *ui;
QTcpSocket *tcpSocket;
QFile file;
QString fileName;
quint64 fileSize;//文件大小
quint64 reciveSize;//已经接收文件大小
bool isStart;
};
#endif // CLIENTWIDGET_H
clientwidget.cpp
#include "clientwidget.h"
#include "ui_clientwidget.h"
#include
#include
#include
ClientWidget::ClientWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::ClientWidget)
{
ui->setupUi(this);
ui->progressBar->setValue(0);
isStart = true;
//初始化套接字
tcpSocket = NULL;
//分配空间,指定父对象
tcpSocket = new QTcpSocket(this);
//建立连接的信号槽
connect(tcpSocket,&QTcpSocket::connected,[=](){
ui->textEditRead->setText("恭喜,成功连接服务器");
});
//建立连接后收到服务器数据的信号槽
// connect(tcpSocket,&QTcpSocket::readyRead,[=](){
// //获取对方发送的数据
// QByteArray array = tcpSocket->readAll();
// ui->textEditRead->append(array);
// });
//建立连接后收到服务器文件数据的信号槽
connect(tcpSocket,&QTcpSocket::readyRead,[=](){
//获取对方发送的文件数据
QByteArray buf = tcpSocket->readAll();
if(isStart==true)
{
isStart = false;
//解析头部信息,初始化
fileName = QString(buf).section("##",0,0);
fileSize = QString(buf).section("##",1,1).toInt();
reciveSize = 0;
//打开文件
file.setFileName("../"+fileName);
bool isOK = file.open(QIODevice::WriteOnly|QIODevice::Append);
if(isOK == false)
{
// tcpSocket->disconnectFromHost();
// tcpSocket->close();
QMessageBox::information(this,"提示:","打开文件错误");
// return ;
}
//初始化进度条
ui->progressBar->setMinimum(0);
ui->progressBar->setMaximum(fileSize/1024);
ui->progressBar->setValue(0);
}
else
{
//文件信息
quint64 len = file.write(buf);
if(len>0)
{
reciveSize+=len;
}
//更新进度条
ui->progressBar->setValue(reciveSize/1024);
if(reciveSize==fileSize)
{
//传输文件完毕
// file.close();
QMessageBox::information(this,"提示:","文件接收完毕");
// tcpSocket->disconnectFromHost();
// tcpSocket->close();
}
}
});
setWindowTitle(QString("TCP客户端"));
}
ClientWidget::~ClientWidget()
{
delete ui;
}
void ClientWidget::on_buttonSend_clicked()
{
//获取编辑内容
QString str = ui->textEditWrite->toPlainText();
//发送数据
tcpSocket->write(str.toUtf8().data());
}
void ClientWidget::on_buttonClose_clicked()
{
tcpSocket->disconnectFromHost();
}
void ClientWidget::on_ButtonConnect_clicked()
{
//获取服务器IP和端口
QString ip = ui->lineEditIP->text();
qint16 port = ui->lineEditPort->text().toInt();
//主动连接服务器
tcpSocket->connectToHost(QHostAddress(ip),port);
ui->progressBar->setValue(0);
}