Qt6 upload multiple files
-
Hello
I'm trying to make a small application to download Lego assembly instructions but I have a problem, only the last element of my address list is taken into account and I don't understand whyhere is my code
main.cpp#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
mainwindow.cpp
#include "mainwindow.h" #include "./ui_mainwindow.h" #include <QUrl> #include "filedownloader.h" #include <QFile> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_download_clicked() { QList<QString> references = {"6145884","6145887","4656079"}; QString baseUrlStr = "https://www.lego.com/cdn/product-assets/product.bi.core.pdf/"; for (int i=0; i<references.size(); i++) { QUrl pdfurl = baseUrlStr + references[i]+".pdf"; File = "C:\\notice_lego\\" + references[i] + ".pdf"; qDebug() << pdfurl; m_pPdfCtrl = new FileDownloader(pdfurl, this); connect(m_pPdfCtrl, SIGNAL (downloaded()), this, SLOT (download())); } } void MainWindow::download() { QByteArray pdf = m_pPdfCtrl->downloadedData(); qDebug() << File; QFile file (File); if (!file.open(QFile::WriteOnly)) { qDebug()<< "impossible d'ouvrir le fichier demandé"; } else { file.write(pdf); file.close(); } }
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include "filedownloader.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); QString File; private slots: void on_pushButton_download_clicked(); void download(); private: Ui::MainWindow *ui; FileDownloader *m_pPdfCtrl; }; #endif // MAINWINDOW_H
filedownloader.cpp
FileDownloader::FileDownloader(QUrl pdfUrl, QObject *parent) : QObject(parent) { connect( &m_WebCtrl, SIGNAL (finished(QNetworkReply*)), this, SLOT (fileDownloaded(QNetworkReply*)) ); QNetworkRequest request(pdfUrl); m_WebCtrl.get(request); } FileDownloader::~FileDownloader() { } void FileDownloader::fileDownloaded(QNetworkReply* pReply) { m_DownloadedData = pReply->readAll(); //emit a signal pReply->deleteLater(); emit downloaded(); } QByteArray FileDownloader::downloadedData() const { return m_DownloadedData; }
filedownloader.h
#ifndef FILEDOWNLOADER_H #define FILEDOWNLOADER_H #include <QObject> #include <QByteArray> #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkReply> class FileDownloader : public QObject { Q_OBJECT public: explicit FileDownloader(QUrl pdfUrl, QObject *parent = 0); virtual ~FileDownloader(); QByteArray downloadedData() const; signals: void downloaded(); private slots: void fileDownloaded(QNetworkReply* pReply); private: QNetworkAccessManager m_WebCtrl; QByteArray m_DownloadedData; }; #endif // FILEDOWNLOADER_H
filedownload.h and filedownload.cpp are from here https://wiki.qt.io/Download_Data_from_URL If you have any information to give me I would be delighted.
-
@jennif56 said in Qt6 upload multiple files:
m_pPdfCtrl = new FileDownloader(pdfurl, this); connect(m_pPdfCtrl, SIGNAL (downloaded()), this, SLOT (download()));
You do this each time round the loop, without waiting for the download to finish.
QByteArray pdf = m_pPdfCtrl->downloadedData();
You do this in the
MainWindow::download()
slot. It uses the current value ofm_pPdfCtrl
. Which keeps changing per the earlier loop. So by the time it is hitm_pPdfCtrl
is doubtless always on the final iteration. There are other member variables which also look like they are being reused each time.Either wait for one to finish before starting the next so that you can use
m_pPdfCtrl
(and other member variables) correctly if you are happy to download in serial or allow for multiple instances correctly if you want to download in parallel. -
@jennif56 said in Qt6 upload multiple files:
I modified my code which now seems to work, I no longer use filedownloader,
but now I'm stuck on how to save the file at File addressmainwindow.cpp
#include "mainwindow.h" #include "./ui_mainwindow.h" #include <QUrl> #include <QFile> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_download_clicked() { QList<QString> references = {"6145884","6145887","4656079"}; QString baseUrlStr = "https://www.lego.com/cdn/product-assets/product.bi.core.pdf/"; for (int i=0; i<references.size(); i++) { MainWindow *item = new MainWindow; File = "C:\\notice_lego\\" + references[i] + ".pdf"; QUrl pdfurl = baseUrlStr + references[i]+".pdf"; item->getPdf(pdfurl); qDebug() << baseUrlStr + references[i]+".pdf"; } } void MainWindow::getPdf(QUrl url) { qDebug() << File; QNetworkAccessManager* man = new QNetworkAccessManager( this ); connect(man, SIGNAL(finished(QNetworkReply*)), this, SLOT(reply(QNetworkReply*))); man->get(QNetworkRequest(url)); } void MainWindow::reply(QNetworkReply* reply) { QByteArray pdf; pdf = reply->readAll(); qDebug() << pdf.size(); QFile file (File); if (!file.open(QFile::WriteOnly)) { qDebug()<< "impossible d'ouvrir le fichier demandé"; } else { file.write(pdf); file.close(); } }
-
@jennif56 said in Qt6 upload multiple files:
but now I'm stuck on how to save the file at File address
I don't know what that means. You seem to have a
MainWindow::reply()
which saves a file.MainWindow *item = new MainWindow; item->getPdf(pdfurl);
You certainly will not want this, why would you create a new instance of
MainWindow
? You can just callgetPdf(pdfurl)
since you are already inside aMainWindow
method. -
@jennif56 said in Qt6 upload multiple files:
is always the last one in the loop ("C:\notice_lego\4656079.pdf")
What do you expect? Since QNetworkManager is async your loop is already done when the download of the first item finished.
QNetworkAccessManager* man = new QNetworkAccessManager( this );
You create a new QNetworkManager here in every call ...
connect(man, SIGNAL(finished(QNetworkReply*)), this, SLOT(reply(QNetworkReply*)));
Please use the pmf style syntax for connects as shown in the documentation.
And while you're at it you can pass the filename in a lambda
void MainWindow::getPdf(const QUrl &url, const QString &filename) { auto rpl = man->get(QNetworkRequest(url)); connect(reply , &QNetworkReply::finished, this, [this, rpl, filename]() { reply(rpl, filename); }); }