本文实例为大家分享了QT实现文件传输功能的具体代码,供大家参考,具体内容如下过程如下:1、服务器端设置监听套接字,开始监听;2、客户端在连接成功时开始传送文件,有connected()信号连接send...

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

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