Trouble understanding how to handle unsupportedContent() signal and actual saving of file
-
Hello!
I made a little download test program to test unsupportedContent(QNetworkReply*) handling.
The trouble for me is now how and where to handle the actual "Save File dialog" stuff ???
This test code is for both normal file URL's like (http://download.winzip.com/winzip180.exe)
and for dynamically generated files (has "Content-Disposition" header that has the filename to save in it)Any advise how to do this correctly and efficiently ?
@class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void slot_unsupportedContent(QNetworkReply * reply);
void slot_downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
void slot_finished();
private:
Ui::MainWindow *ui;
QString fileName;
};#include <QMessageBox>
#include <QDebug>
#include <QFileInfo>
#include <QFileDialog>
#include <QDir>MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);this->ui->webView->page()->setForwardUnsupportedContent(true); connect(this->ui->webView->page(),SIGNAL(unsupportedContent(QNetworkReply*)),this,SLOT(slot_unsupportedContent(QNetworkReply*))); /* To test dynamically generated file download ("Content-Disposition" header) * Just give that page some YouTube URL (like https://www.youtube.com/watch?v=UtBysnK0CQM) * and continue so long untill you see the Download button and see what happens */ this->ui->webView->load(QUrl("http://convert2mp3.net/en/index.php?p=home")); /* To test normal URL download, that is URL contains filename part */ //this->ui->webView->load(QUrl("http://www.winzip.com/win/en/dprob.html"));
}
void
MainWindow::slot_unsupportedContent(QNetworkReply * reply)
{
/* To see the download progress.
* Downloading is actually in progress already in this point!
* That is, reply is already downloading data */
connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(slot_downloadProgress(qint64,qint64)));/* To check the final download status, and if no error then save to disk. * But where should the user be asked the filename to save with * QFileDialog::getSaveFileName() ??? * * If it's done here then the download could be finished already * (if very small file) and then slot_finished() called * before user even had chance to give filename to save! * (you can see the progressbar starting going immediately before savedialog) * * If it's done at the slot_finished() then with large files * user has to wait untill whole download complete before he/she * can give filename to save. * * Does this download have to do "twice" ? Once in here to get the * metadata from reply so that user can save with correct filename * and then at the end of this slot_unsupportedContent() * call download method or emit some signal to start download method ? * Sounds wastefull of bandwidth... * * Isn't there any way to postpone the actual coming of data from reply * object untill the metadata for filename has been gotted ??? */ connect(reply,SIGNAL(finished()),this,SLOT(slot_finished())); /* Diagnostic purposes only. Especially to see if server sends * "Content-Disposition" header when it send dynamically (usually with php) * generated file */ QList<QByteArray> h = reply->rawHeaderList(); foreach(QByteArray x,h) { qDebug() << x << "\t" << reply->rawHeader(x); } QString baseFileName; if(!reply->rawHeader("Content-Disposition").isEmpty()) { baseFileName = QString(reply->rawHeader("Content-Disposition")).replace(QRegular[removed]"(.*filename=)\"(.*)\""),"\\2"); } else { baseFileName = reply->url().path().split("/").last(); } fileName = QFileDialog::getSaveFileName(this, tr("Save File"), QDir::currentPath() + "/" + baseFileName);
}
void
MainWindow::slot_downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
this->ui->progressBar->setMaximum(bytesTotal);
this->ui->progressBar->setValue(bytesReceived);
}void
MainWindow::slot_finished()
{
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());if(reply) switch(reply->error()) { case QNetworkReply::NoError: { qDebug() << "Download Finished!"; QFile file(this->fileName); if(file.open(QIODevice::WriteOnly)) { QByteArray data = reply->readAll(); qDebug() << "Writted " << file.write(data) << " BYTES"; file.close(); } } break; }
}
@