Вопрос

In my App, I have a method to upload files to the server, this works fine.

But when I call this method multiple times at once (like iterating over the result of a chooseFilesDialog) the first 7 (more or less) files are uploaded correctly, the others never get uploaded.

I think this has to be linked with the fact the server doesn't allow more than X connections from the same source maybe?

How can I make sure the upload waits for a free, established connection?

this is my method:

QString Api::FTPUpload(QString origin, QString destination)
{
    qint64 timestamp = QDateTime::currentMSecsSinceEpoch();
    QUrl url("ftp://ftp."+getLSPro("domain")+destination);
    url.setUserName(getLSPro("user"));
    url.setPassword(getLSPro("pwd"));

    QFile *data = new QFile(origin, this);
    if (data->open(QIODevice::ReadOnly))
    {
        QNetworkAccessManager *nam = new QNetworkAccessManager();
        QNetworkReply *reply = nam->put(QNetworkRequest(url), data);
        reply->setObjectName(QString::number(timestamp));
        connect(reply, SIGNAL(uploadProgress(qint64, qint64)), SLOT(uploadProgress(qint64, qint64)));

        return QString::number(timestamp);
    }
    else
    {
        qDebug() << "Could not open file to FTP";
        return 0;
    }
}

void Api::uploadProgress(qint64 done, qint64 total) {
    QNetworkReply *reply = (QNetworkReply*)sender();
    emit broadCast("uploadProgress","{\"ref\":\""+reply->objectName()+"\" , \"done\":\""+QString::number(done)+"\", \"total\":\""+QString::number(total)+"\"}");
}
Это было полезно?

Решение

First, don't create a QNetworkManager every time you start an upload.
Second, you definitely have to delete everything you new(), otherwise you are left with memory leaks. This includes the QFile, the QNetworkManager AND the QNetworkReply (!).
Third, you have to wait for the finished() signal.

Api::Api() {  //in the constructor create the network access manager
    nam = new QNetworkAccessManager()
    QObject::connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(finished(QNetworkReply*)));
}

Api::~Api() {  //in the destructor delete the allocated object
    delete nam;
}

bool Api::ftpUpload(QString origin, QString destination) {
    qint64 timestamp = QDateTime::currentMSecsSinceEpoch();
    QUrl url("ftp://ftp."+getLSPro("domain")+destination);
    url.setUserName(getLSPro("user"));
    url.setPassword(getLSPro("pwd"));

    //no allocation of the file object;
    //will automatically be destroyed when going out of scope
    //I use readAll() (see further) to fetch the data
    //this is OK, as long as the files are not too big
    //If they are, you should allocate the QFile object
    //and destroy it when the request is finished
    //So, you would need to implement some bookkeeping,
    //which I left out here for simplicity
    QFile file(origin);
    if (file.open(QIODevice::ReadOnly)) {
        QByteArray data = file.readAll();   //Okay, if your files are not too big
        nam->put(QNetworkRequest(url), data);
        return true;

        //the finished() signal will be emitted when this request is finished
        //now you can go on, and start another request
    }
    else {
      return false;
    }
}

void Api::finished(QNetworkReply *reply) {
    reply->deleteLater();  //important!!!!
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top