02 Qt发送文件和接收

借助上一篇文章的内容,在原有的TCP通讯的基础上,在服务端和客户端之间发送文件。

首先把在客户端加一个用于显示发送进度的进度条,在服务器端把原有的发送和关闭换为选择和发送,如下图所示
客户端
服务器端

在客户端连接服务器之后建立套接字,服务器便通过判断是否有建立套接字,然后才可以选择文件,在connect函数内写上

//成功连接后,才能按选择文件
ui->buttonFile->setEnabled(true);

之后我们在serverwidget.h中定义文件,文件名,文件大小等变量,在serverwidget.cpp中引用,在选择按钮中建立槽函数。

QString filePath=QFileDialog::getOpenFileName(this,"open","../");
    if(false==filePath.isEmpty())
    {
        fileName.clear();
        fileSize=0;

        //获取文件信息
        QFileInfo info(filePath);
        fileName=info.fileName();//获取文件名字
        fileSize=info.size();

        sendSize=0;


        //只读方式打开文件

        file.setFileName(filePath);

        bool isOk=file.open(QIODevice::ReadOnly);
        if(false==isOk)
        {
            qDebug() << "只读方式打开文件失败 77 ";
        }

        ui->buttonFile->setEnabled(false);
        ui->buttonSend->setEnabled(true);
    }
    else
    {
        qDebug() << "选择文件路径出错 62";
    }

之后便通过发送按钮进行发送,在槽函数内我们要记住要定义文件头,防止黏包,也起到加密作用,之后再20ms后启动定时器开始发送

void ServerWidget::on_buttonSend_clicked()
{
    //先发送文件头信息
    QString head=QString("%1##%2").arg(fileName).arg(fileSize);
    //发送头部信息
    qint64 len =tcpSocket->write(head.toUtf8());
    if(len>0)
    {
        //发送真正的文件信息
        //防止TCP黏包文件
        timer.start(20);

    }
    else
    {
        qDebug() << "头部信息发送失败 110";
        file.close();
        ui->buttonFile->setEnabled(true);
        ui->buttonSend->setEnabled(false);

    }
}

还有要特别注意发送必须要使用定时器,要不然发送会失败,我们在主函数connect函数下面添加定时器,还有在serverwidget.h中要定义变量QTimer timer;

connect(&timer,&QTimer::timeout,
            [=]()
    {
        //关闭定时器
        timer.stop();
        //发送文件
        sendData();
    });

这样发送文件便完成了,紧接着我们在服务端中对发送过来的文件进行判断是否接收完成,把接收完成的信息返回给服务器,告诉它我已经接收完成。
首先,我们定义一个标志位isstart,用于判断是否可以接收,开始接收后,标志位就置false,防止再次接收。然后我们要对接收到的数据处理,判断文件头是否就是我们服务端发送的文件头,是就开始接收。

if(true==isStart)
{   
    //接收头
    isStart=false;
    //解析头部信息buf="hello##1024"
    //                    QString str="hello##1024mike";
    //                    str.section("##",0,0);

    fileName=QString(buf).section("##",0,0);
    fileSize=QString(buf).section("##",1,1).toInt();
    recvSize=0;

    //打开文件
    file.setFileName(fileName);

    bool isOk=file.open(QIODevice::WriteOnly);
    if(false==isOk)
    {
         qDebug() << "WritOnly error 40";
    }

    //弹出对话框,显示接收文件的大小
    QString str=QString("接收的文件: [%1:%2kb]").arg(fileName).arg(fileSize);
    QMessageBox::information(this,"文件信息",str);

    //设置进度条
    ui->progressBar->setMinimum(0);
    ui->progressBar->setMaximum(fileSize/1024);
    ui->progressBar->setValue(0);
}

接收完后,我们在下面写一个else,判断已经接收完成,给服务器发送信息

else //文件信息
{
    qint64 len =file.write(buf);
    if(len>0)
    {
          recvSize+=len;
          qDebug() <<len;
    }
    ui->progressBar->setValue(recvSize/1024);

    if(recvSize==fileSize)
    {

         QString str=QString::number(recvSize);

         //tcpSocket->write(str.toUtf8().data());
         tcpSocket->write("file done");

         file.close();
         QMessageBox::information(this,"完成","文件接收完成");

         tcpSocket->disconnectFromHost();
         tcpSocket->close();
     }
}

然后在服务器端写上判断是否客户端是否接收完成

connect(tcpSocket,&QTcpSocket::readyRead,
                [=]()
        {
            QByteArray buf=tcpSocket->readAll();
            if(QString(buf)=="file done")
            {
                //文件接收完毕
                ui->textEdit->append("接收完毕");
                file.close();


                //断开服务端端口
                tcpSocket->disconnectFromHost();
                tcpSocket->close();
            }
            else
            {
                qDebug() <<buf;
            }
        });

到这里就基本上完成了
这里写图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值