简体   繁体   中英

TLS initialization failed and SSL handshake failed QtNetwork

I'm using QtNetwork, QNetworkAccessManager, QNetworkRequest, QNetworkReply to set up a modal dialog to download any file provided in the URL path.

When I start the download, I get an error saying either Download failed: TLS initialization or ``Download failed: SSL handshake failed`, depending on different machines I test this on.

This seems to be an OpenSSL issue. Is there a way to fix the error without requiring the user machine to have OpenSSL installed?

This is my download class

fAppDownloadDialog::fAppDownloadDialog()
{
  // set up UI modal dialog
  // ...
  // ...

  connect(cancelButton, SIGNAL(clicked()), this, SLOT(CancelButtonPressed()));
  connect(confirmButton, SIGNAL(clicked()), this, SLOT(ConfirmButtonPressed()));
}

void fAppDownloadDialog::CancelButtonPressed()
{
    this->close();
}

void fAppDownloadDialog::ConfirmButtonPressed()
{
    manager = new QNetworkAccessManager(this);

    QFileInfo fileInfo(url.path()); // QUrl url defined in .h
    QString fileName = fileInfo.fileName(); 

    fullPath = downloadPath + fileName; // QString fullPath, downloadPath in .h

    if (QFile::exists(fullPath)) {
        if (QMessageBox::question(this, tr("HTTP"),
                tr("There already exists a file %1. Overwrite?").arg(fileName),
                QMessageBox::Yes|QMessageBox::No, QMessageBox::No)
                == QMessageBox::No)
                return;
        QFile::remove(fullPath);
    }

    file = new QFile(fullPath); // QFile file in .h
    if (!file->open(QIODevice::WriteOnly)) {
        QMessageBox::information(this, tr("HTTP"),
                    tr("Unable to save the file %1: %2")
                    .arg(fileName).arg(file->errorString()));
        delete file;
        file = 0;
        return;
    }

    // used for progressDialog
    // This will be set true when canceled from progress dialog
    httpRequestAborted = false;

    startRequest(url);

    this->close();
}

// This will be called when download button is clicked
void fAppDownloadDialog::startRequest(QUrl url)
{
    // get() method posts a request
    // to obtain the contents of the target request
    // and returns a new QNetworkReply object
    // opened for reading which emits
    // the readyRead() signal whenever new data arrives.
    reply = manager->get(QNetworkRequest(url));

    // Whenever more data is received from the network,
    // this readyRead() signal is emitted
    connect(reply, SIGNAL(readyRead()),
            this, SLOT(httpReadyRead()));

    // This signal is emitted when the reply has finished processing.
    // After this signal is emitted,
    // there will be no more updates to the reply's data or metadata.
    connect(reply, SIGNAL(finished()),
            this, SLOT(httpDownloadFinished()));
}


void fAppDownloadDialog::httpReadyRead()
{
    // this slot gets called every time the QNetworkReply has new data.
    // We read all of its new data and write it into the file.
    // That way we use less RAM than when reading it at the finished()
    // signal of the QNetworkReply
    if (file)
        file->write(reply->readAll());
}

// When download finished or canceled, this will be called
void fAppDownloadDialog::httpDownloadFinished()
{
  // when canceled
    if (httpRequestAborted) {
        if (file) {
            file->close();
            file->remove();
            delete file;
            file = 0;
        }
        reply->deleteLater();

        return;
    }

    // download finished normally
    file->flush();
    file->close();

    // get redirection url
    QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
    if (reply->error()) {
        file->remove();
        QMessageBox::information(this, tr("HTTP"),
                                tr("Download failed: %1.")
                                .arg(reply->errorString()));
    } else if (!redirectionTarget.isNull()) {
        QUrl newUrl = url.resolved(redirectionTarget.toUrl());
        if (QMessageBox::question(this, tr("HTTP"),
                                tr("Redirect to %1 ?").arg(newUrl.toString()),
                                QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
            url = newUrl;
            reply->deleteLater();
            file->open(QIODevice::WriteOnly);
            file->resize(0);
            startRequest(url);
            return;
        }
    } else {
        QString fileName = QFileInfo(QUrl(qInputLink).path()).fileName();

    }

    reply->deleteLater();
    reply = 0;
    delete file;
    file = 0;
    manager = 0;
}

// During the download progress, it can be canceled
void fAppDownloadDialog::cancelDownload()
{
    httpRequestAborted = true;
    reply->abort();

    this->close();
}

You need to provide libssl and libcrypto libraries for your application.

If you have installed Qt with Qt Installer on Windows, run Qt's Maintainer Tools and install OpenSSL Toolkit:

在此处输入图像描述

then copy ssl and crypto dll's right to the place where your app.exe file placed. Dll's could be found in QTSDK root subfolder Tools\OpenSSL\Win_x64\bin

在此处输入图像描述

On linux just install/compile OpenSSL and link.so's to the right place

Adding OpenSSL Support

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM