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;
}
}
↧