QT开发中文网

使用 Qt 框架编写一个类,该类可以通过用户名和密码登录远程文件服务器,可以发送文件,并实时通知文件传输的状态、进度的信息,保证文件传输在子线程中运行

以下是使用 Qt 框架编写的一个类,包含登录远程文件服务器、发送文件和实时通知文件传输状态、进度信息的功能,同时保证所有文件传输在子线程中运行。

#include <QtCore>
#include <QtNetwork>

class RemoteFileClient : public QObject
{
    Q_OBJECT

public:
    explicit RemoteFileClient(QObject *parent = nullptr)
        : QObject(parent)
    {}

    void login(const QString &username, const QString &password, const QString &serverAddress, int port)
    {
        // 创建 TCP 连接,并在连接成功后发送登录请求
        tcpSocket.connectToHost(serverAddress, port);
        if (tcpSocket.waitForConnected()) {
            sendLoginRequest(username, password);
        } else {
            emit loginError("无法连接到服务器:" + tcpSocket.errorString());
        }
    }

    void sendFile(const QString &localFilePath, const QString &remoteFilePath)
    {
        // 创建一个新线程,用于发送文件,并将其移动到该线程中执行
        QThread *thread = new QThread;
        FileSender *sender = new FileSender(localFilePath, remoteFilePath, &tcpSocket);
        sender->moveToThread(thread);

        // 连接信号和槽函数,实现实时通知文件传输状态、进度信息
        connect(sender, &FileSender::finished, thread, &QThread::quit);
        connect(sender, &FileSender::statusUpdate, this, &RemoteFileClient::sendStatusUpdate);
        connect(sender, &FileSender::error, this, &RemoteFileClient::sendError);

        // 启动子线程并开始文件传输
        connect(thread, &QThread::started, sender, &FileSender::send);
        thread->start();
    }

signals:
    void loginSuccess();
    void loginError(const QString &errorMessage);
    void sendStatusUpdate(const QString &status, int progress);
    void sendError(const QString &errorMessage);

private slots:
    void handleLoginResponse()
    {
        // 解析登录响应并发送信号
        QByteArray responseData = tcpSocket.readAll();
        if (responseData == "success") {
            emit loginSuccess();
        } else {
            emit loginError("登录失败:" + responseData);
        }
    }

private:
    QTcpSocket tcpSocket;

    void sendLoginRequest(const QString &username, const QString &password)
    {
        // 发送登录请求,并在收到响应后处理
        QString requestData = "login " + username + " " + password;
        tcpSocket.write(requestData.toUtf8());
        if (tcpSocket.waitForBytesWritten() && tcpSocket.waitForReadyRead()) {
            handleLoginResponse();
        } else {
            emit loginError("登录超时或中断:" + tcpSocket.errorString());
        }
    }
};

class FileSender : public QObject
{
    Q_OBJECT

public:
    explicit FileSender(const QString &localFilePath, const QString &remoteFilePath, QTcpSocket *socket, QObject *parent = nullptr)
        : QObject(parent),
          localFile(localFilePath),
          remoteFile(remoteFilePath),
          tcpSocket(socket)
    {}

signals:
    void finished();
    void statusUpdate(const QString &status, int progress);
    void error(const QString &errorMessage);

public slots:
    void send()
    {
        // 打开本地文件,并准备向服务器发送数据
        QFile file(localFile);
        if (!file.open(QIODevice::ReadOnly)) {
            emit error("无法打开本地文件:" + file.errorString());
            return;
        }

        // 发送文件名和大小,并在收到响应后开始发送文件内容
        qint64 fileSize = file.size();
        QString requestData = "send " + remoteFile + " " + QString::number(fileSize);
        tcpSocket->write(requestData.toUtf8());
        if (tcpSocket->waitForBytesWritten() && tcpSocket->waitForReadyRead()) {
            QByteArray responseData = tcpSocket->readAll();
            if (responseData == "ready") {
                sendFileContent(&file, fileSize);  // 开始发送文件内容
            } else {
                emit error("服务器拒绝接收文件:" + responseData);
            }
        } else {
            emit error("请求超时或中断:" + tcpSocket->errorString());
        }
    }

private:
    QString localFile, remoteFile;
    QTcpSocket *tcpSocket;

    void sendFileContent(QFile *file, qint64 fileSize)
    {
        // 定义缓冲区和每次读取的字节数
        QByteArray buffer;
        const int bufferSize = 1024 * 1024;  // 每次 1MB

        // 发送文件内容,并实时通知状态、进度信息
        qint64 totalBytesSent = 0;
        while (totalBytesSent < fileSize) {
            buffer = file->read(qMin(fileSize - totalBytesSent, qint64(bufferSize)));
            qint64 bytesSent = tcpSocket->write(buffer);
            totalBytesSent += bytesSent;

            int progressPercent = int(totalBytesSent * 100 / fileSize);
            emit statusUpdate("正在发送", progressPercent);
        }

        // 关闭文件和套接字,并发送完成信号
        file->close();
        tcpSocket->waitForBytesWritten();
        tcpSocket->close();
        emit finished();
    }
};

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://qt.0voice.com/?id=1401

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?