2010-12-08 2 views
7

에서 Qt를에서 파일을 다운로드하고,이 기사를 건너 왔어요 :내가 파일을 다운로드해야 내 프로그램에서 URL

http://www.java2s.com/Code/Cpp/Qt/DownloadfromURL.htm

이 코드는하지만 내 프로그램에 작업 그래서 맞지 않습니다 그것을 다시 코딩했다. 나는 그것을 모두 완료하지는 않았지만 나는 기본 코드를 가지고있다. 그러나 테스트 할 때 보내기 오류보고 창이 나타납니다. 나는 그것이 아니다 말했듯이 QtDownload.cpp

#include "qtdownload.h" 

#include <QUrl> 
#include <QNetworkRequest> 
#include <QFile> 

QtDownload::QtDownload() 
    : QObject(0) 
{ 
    this->connectSignalsAndSlots(); 
} 

QtDownload::~QtDownload() 
{ 
    if (reply != 0) 
     delete reply; 
} 

void QtDownload::connectSignalsAndSlots() 
{ 
    QObject::connect(&manager, SIGNAL(finished(QNetworkReply*)),this, SLOT(downloadFinished(QNetworkReply*))); 
    QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloadProgress(qint64,qint64))); 
} 

void QtDownload::setTarget(const QString &t) 
{ 
    this->target = t; 
} 

void QtDownload::downloadFinished(QNetworkReply *data) 
{ 
    QFile localFile("downloadedfile"); 
    if (!localFile.open(QIODevice::WriteOnly)) 
     return; 
    localFile.write(data->readAll()); 
    localFile.close(); 
    delete data; 
    data = 0; 
} 

void QtDownload::download() 
{ 
    QUrl url = QUrl::fromEncoded(this->target.toLocal8Bit()); 
    QNetworkRequest request(url); 
    this->reply = manager.get(request); 
} 

void QtDownload::downloadProgress(qint64 recieved, qint64 total) 
{ 

} 

MAIN.CPP

#include "qtdownload.h" 
#include <QTimer> 

int main() 
{ 
    QtDownload dl; 
    dl.setTarget("http://www.java2s.com/Code/Cpp/Qt/DownloadfromURL.htm"); 

    QTimer::singleShot(0, &dl, SLOT(download())); 
} 

QtDownload.h

#include <QObject> 
#include <QString> 
#include <QNetworkAccessManager> 
#include <QNetworkReply> 


class QtDownload : public QObject 
{ 
    Q_OBJECT 
public: 
    explicit QtDownload(); 
    ~QtDownload(); 

    void setTarget(const QString& t); 

private: 
    QNetworkAccessManager manager; 
    QNetworkReply* reply; 
    QString target; 
    void connectSignalsAndSlots(); 

signals: 

public slots: 
    void download(); 
    void downloadFinished(QNetworkReply* data); 
    void downloadProgress(qint64 recieved, qint64 total); 
}; 

:

는 지금까지 내 코드입니다 완전히 끝났지 만 나는 자고있다. 계속 진행하기 전에이 부분을 사용해보십시오.

나는 또한 Qt를 처음 사용하므로 모든 팁을 높이 평가할 수 있습니다.

답변

5
  • 당신은 초기화되지 않은 포인터를 사용하고, 그래서 아무데도 밖으로을 지적하지 않는다. 생성자에서 NULL으로 reply을 초기화하십시오.
  • 생성자가 아닌 reply을 만든 후에 (reply = manager.get(...)) 연결해야합니다.
  • QNetworkReplyQNetworkManagerdocs say으로 삭제되지 않습니다 :

이 신호에 연결된 슬롯에 응답 개체를 삭제하지 마십시오. deleteLater()를 사용하십시오.

QNetworkReply의 전화 번호는 finished입니다. 0data0 만 설정합니다 매개 변수 값을 설정 finished 슬롯에

  • , 아닌 클래스 멤버 reply. 불필요한 코드 줄입니다. 대신 reply 회원을 NULL으로 설정해야합니다.

또한 전체 파일이 현재 사례의 메모리에 버퍼링되므로 데이터를 청크 할 때마다 파일에 기록하는 것을 고려해야합니다. 뾰족한 URL의 파일이 크면 소프트웨어의 엄청난 메모리 사용으로 이어질 수 있습니다.

1

Qt4의 이벤트 루프를 시작하려면 QCoreApplication이 필요합니다. 이 같은 뭔가가 작동합니다 (테스트하지) :

int main(int argc, char **argv) { 
    QCoreApplication app(argc, argv); 
    QtDownload dl; 
    dl.setTarget("http://www.java2s.com/Code/Cpp/Qt/DownloadfromURL.htm"); 

    dl.download(); 
    QObject::connect(app, SIGNAL(aboutToQuit()), app, SLOT(quit())); 
    return app.exec(); 
} 

편집 : 새 버전

내가 찾은 몇 가지 문제 :

  1. 당신은 또한, 사용자 정의 응답을 결코 필요 없어 생성자에서 0으로 설정하십시오. 따라서 사용하지 않으면 ~ QtDownload()에서 임의의 메모리 조각이 삭제됩니다.
  2. QtDownload::downloadFinished 안에 data을 삭제하려고했는데,이를 수행해서는 안되며 Qt에서 처리하므로 두 번 삭제되었습니다.
  3. # 2 때문에 reply 번을 3 번 삭제했습니다.

    qtdownload.h :

    #include <QObject> 
    #include <QString> 
    #include <QtNetwork/QNetworkAccessManager> 
    #include <QtNetwork/QNetworkReply> 
    
    
    class QtDownload : public QObject { 
        Q_OBJECT 
    public: 
        explicit QtDownload(); 
        ~QtDownload(); 
    
        void setTarget(const QString& t); 
    
    private: 
        QNetworkAccessManager manager; 
        QString target; 
    
    signals: 
        void done(); 
    
    public slots: 
        void download(); 
        void downloadFinished(QNetworkReply* data); 
        void downloadProgress(qint64 recieved, qint64 total); 
    }; 
    

    qtdownload.cpp : 여기

는 수정 된 버전의

#include "qtdownload.h" 
#include <QCoreApplication> 
#include <QUrl> 
#include <QNetworkRequest> 
#include <QFile> 
#include <QDebug> 

QtDownload::QtDownload() : QObject(0) { 
    QObject::connect(&manager, SIGNAL(finished(QNetworkReply*)),this, SLOT(downloadFinished(QNetworkReply*))); 
} 

QtDownload::~QtDownload() { 

} 


void QtDownload::setTarget(const QString &t) { 
    this->target = t; 
} 

void QtDownload::downloadFinished(QNetworkReply *data) { 
    QFile localFile("downloadedfile"); 
    if (!localFile.open(QIODevice::WriteOnly)) 
     return; 
    const QByteArray sdata = data->readAll(); 
    localFile.write(sdata); 
    qDebug() << sdata; 
    localFile.close(); 

    emit done(); 
} 

void QtDownload::download() { 
    QUrl url = QUrl::fromEncoded(this->target.toLocal8Bit()); 
    QNetworkRequest request(url); 
    QObject::connect(manager.get(request), SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloadProgress(qint64,qint64))); 

} 

void QtDownload::downloadProgress(qint64 recieved, qint64 total) { 
    qDebug() << recieved << total; 
} 

MAIN.CPP :

#include <QtCore> 
#include "qtdownload.h" 
int main(int argc, char **argv) { 
    QCoreApplication app(argc, argv); 
    QtDownload dl; 
    dl.setTarget("http://localhost"); 

    dl.download(); 
    //quit when the download is done. 
    QObject::connect(&dl, SIGNAL(done()), &app, SLOT(quit())); 
    return app.exec(); 
} 
+0

아직 오류보고가 전송되지 않습니다. –

+0

코드가 수정되었습니다. – OneOfOne

+0

죄송합니다, 귀하의 답변에 많은 오류가 –

1

당신이 요청으로, 일반적인 코멘트 :

void QtDownload::downloadFinished(QNetworkReply *data) 
{ 
    QFile localFile("downloadedfile"); 
    if (!localFile.open(QIODevice::WriteOnly)) 
     return; 
    localFile.write(data->readAll()); 
    localFile.close(); 
    delete data; 
    data = 0; 
} 
  1. 당신은 한 덩어리의 모든 데이터를 읽습니다. 큰 파일에는 좋지 않습니다. 점진적으로 읽는 것이 좋습니다.
  2. 슬롯에서 인수 데이터를 삭제하는 것은 위험합니다. 네트워크 관리자가 객체 "데이터"포인트를 완성 된 신호를 방출 한 직후까지 계속 사용 (또는 삭제)하는지 여부를 알지 못합니다. 관리자가 소유 한 경우 문서를 확인하기 위해 뭔가를 묻는다면 응답을 삭제할 필요가 없을 것입니다.
  3. 파일을 열지 못하면 데이터가 삭제되지 않습니다. 그래서 무엇이 옳건, 일관성이 없습니다. 누출되거나 이중 삭제 위험이 있습니다.
  4. localFile.write (data-> readAll())는 모든 데이터를 한 번에 쓸 수 있다고 보장하지 않습니다. 그것이 반환 가치를 가지고있는 이유입니다. 모든 값이 기록되는지 확인하기 위해 검사해야합니다. -1을 반환하면 오류를 처리해야합니다.

    if (reply != 0) 
        delete reply; 
    

생략는 IF. null 포인터를 삭제하는 것은 안전합니다.

관련 문제