我正在努力使这个问题的代码工作。 qt - how to download and save image via http?
它会创建文件,但不会向其写入任何数据。 我最好的猜测是,与信号和插槽的连接不起作用。 我做错了什么?
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
QString getPageImage(QString url = "");
bool saveToDisk(const QString &filename, QIODevice *data);
~MainWindow();
private slots:
void on_btnDownload_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
qdownload.h
#ifndef QDOWNLOADER_H
#define QDOWNLOADER_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QFile>
#include <QStringList>
#include <QDir>
#include <QDebug>
class QDownloader : public QObject
{
Q_OBJECT
public:
explicit QDownloader(QObject *parent = 0);
virtual ~QDownloader();
void setFile(QString fileURL, QString folderName, QString fileName);
private:
QNetworkAccessManager *manager;
QNetworkReply *reply;
QFile *file;
private slots:
void onDownloadProgress(qint64,qint64);
void onFinished(QNetworkReply*);
void onReadyRead();
void onReplyFinished();
};
#endif // QDOWNLOADER_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QNetworkAccessManager"
#include "QNetworkReply"
#include "QFile"
#include "QDebug"
#include "QUrl"
#include "QStringList"
#include "qdownloader.h"
#include <QTimer>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->progressBar->setVisible(false);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_btnDownload_clicked()
{
QString link = ui->txtURL->text();
int issue = ui->sbIssue->value();
ui->progressBar->setMaximum(issue);
ui->progressBar->setValue(0);
ui->progressBar->setVisible(true);
for(int j = 1; j <= issue; j++){
int i = 1;
while(getPageImage(link + "/" + QString::number(j) + "/" + QString::number(i) + "/").length() > 0){
QString filename = "http://" + getPageImage(link + "/" + QString::number(j) + "/" + QString::number(i) + "/");
qDebug() << filename;
QDownloader qDL;
qDL.setFile(filename,ui->txtTitle->text() + "_" + QString::number(j),ui->txtTitle->text() + "_" + QString::number(j) + "_" + QString::number(i));
//qDebug() << getPageImage(link + "/" + QString::number(j) + "/" + QString::number(i) + "/").length();
i++;
}
ui->progressBar->setValue(j);
}
ui->progressBar->setVisible(false);
}
QString MainWindow::getPageImage(QString url){
QString pic = "";
if(url.length() > 0){
QNetworkAccessManager manager;
QNetworkReply *response = manager.get(QNetworkRequest(QUrl(url)));
QEventLoop event;
connect(response,SIGNAL(finished()),&event,SLOT(quit()));
event.exec();
QString html = response->readAll();
if(html.length() > 0){
QStringList str;
str = html.split("\n");
//qDebug() << url;
for (int i = 0; i < str.size(); ++i){
if(str.at(i).contains("id=\"mainImg\"", Qt::CaseInsensitive)){
pic = str.at(i);
pic = pic.remove(QRegExp("<img[^>]*src=['|\"]", Qt::CaseInsensitive));
pic = pic.remove(QString::fromStdString("//"), Qt::CaseInsensitive);
pic = pic.remove('"');
pic = pic.remove("'");
pic = pic.remove('<');
pic = pic.remove('>');
pic = pic.remove(';');
pic = pic.left(pic.length()-1);
//qDebug() << str.at(i);
//qDebug() << pic;
}
}
}else{
pic = "";
}
//qDebug() << "Lines: " << str.size();
}else{
pic = "";
}
return pic;
}
qdownload.cpp
#include "qdownloader.h"
QDownloader::QDownloader(QObject *parent) :
QObject(parent)
{
manager = new QNetworkAccessManager;
}
QDownloader::~QDownloader()
{
manager->deleteLater();
}
void QDownloader::setFile(QString fileURL, QString folderName, QString fileName)
{
QDir dir;
if(dir.exists(folderName)){
//qDebug() << "Existis: " + folderName;
}else{
dir.mkdir(folderName);
//() << "Created: " + folderName;
}
QString filePath = fileURL;
QStringList filePathList = filePath.split('/');
QString fileExt = filePathList.at(filePathList.count() - 1);
fileExt = "jpg";
QString saveFilePath;
saveFilePath = QString(folderName + "/" + fileName + "." + fileExt );
QNetworkRequest request;
request.setUrl(QUrl(fileURL));
reply = manager->get(request);
file = new QFile;
file->setFileName(saveFilePath);
connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(onDownloadProgress(qint64,qint64)));
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(onFinished(QNetworkReply*)));
connect(reply,SIGNAL(readyRead()),this,SLOT(onReadyRead()));
connect(reply,SIGNAL(finished()),this,SLOT(onReplyFinished()));
}
void QDownloader::onDownloadProgress(qint64 bytesRead,qint64 bytesTotal)
{
qDebug(QString::number(bytesRead).toLatin1() +" - "+ QString::number(bytesTotal).toLatin1());
}
void QDownloader::onFinished(QNetworkReply * reply)
{
switch(reply->error())
{
case QNetworkReply::NoError:
{
qDebug("file is downloaded successfully.");
}break;
default:{
qDebug(reply->errorString().toLatin1());
};
}
if(file->isOpen())
{
file->close();
file->deleteLater();
}
}
void QDownloader::onReadyRead()
{
qDebug() << "Ready";
file->open(QIODevice::WriteOnly);
file->write(reply->readAll());
}
void QDownloader::onReplyFinished()
{
if(file->isOpen())
{
file->close();
file->deleteLater();
}
}
答案 0 :(得分:3)
我准备了一个非常基本的例子,可以作为参考。
在“我的”下载程序中的某个位置,我启动了请求:
QNetworkRequest request;
request.setUrl(org);
_reply = _manager->get(request); // Manager is my QNetworkAccessManager
connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(error(QNetworkReply::NetworkError)));
connect(_reply, SIGNAL(downloadProgress(qint64, qint64)),
this, SLOT(updateProgress(qint64, qint64)));
connect(_reply, SIGNAL(finished()),
this, SLOT(finished()));
正如您所看到的,您需要做的就是get()
并正确使用QNetworkReply
的信号。
在“我的”插槽之后:
void MyDownloader::error(QNetworkReply::NetworkError err)
{
// Manage error here.
_reply->deleteLater();
}
void MyDownloader::updateProgress(qint64 read, qint64 total)
{
// This is where you can use the progress info for, lets say, update a progress bar:
// progressBar->setMaximum(total);
// progressBar->setValue(read);
}
void MyDownloader::finished()
{
// Save the image here
QByteArray b = _reply->readAll();
QFile file(des); // "des" is the file path to the destination file
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
out << b;
_reply->deleteLater();
// done
}
请注意,您可以在updateProgress()
中写入文件,而不是在回复完成后立即写入整个文件。
要在updateProgress()
上书写,请在QFile
时间打开和/或创建get
。然后在每次更新时使用回复readAll
并将读取的数据写入文件,然后在finished
时关闭文件。
// ...
_file = new QFile(des);
_reply = _manager->get(request);
/// ...
void MyDownloader::updateProgress(qint64 read, qint64 total)
{
QByteArray b = _reply->readAll();
QDataStream out(_file);
out << b;
}
void MyDownloader::finished()
{
// Done
_reply->deleteLater();
_file->close();
// probably delete the file object too
}