Qt 는 QNetworkAssessManager 를 사용 하여 파일 을 다운로드 합 니 다.
공식 문서:http://doc.qt.io/archives/qt-5.8/qnetworkaccessmanager.html
어 휘 를 잘 아 는 api: post, get, put, head 를 한눈 에 볼 수 있 습 니 다. 물론 쿠키 와 관련 된 방법 도 몇 가지 있 습 니 다.
manager 를 사용 하려 면 몇 가지 종류 가 필요 합 니 다. QNetworkRequest 는 요청 에 사용 되 는 QNetworkReply 가 요청 한 응답 을 받 습 니 다.
예 를 들 어 1. 웹 서버 에서 만 데 이 터 를 요청 하고 get 방법 을 사용 합 니 다.
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
QNetworkRequest request;
request.setUrl(QUrl("http://qt-project.org"));
reply = manager->get(request);
connect(reply, &QNetworkReply::finished, this, &MainWindow::finished);
// finished
QByteArray bytes = reply->readAll();//
2. 서버 에 데 이 터 를 되 돌려 달라 고 요청 하고 post 를 사용 합 니 다. post 에 json 데 이 터 를 추가 할 때:
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkRequest request;
// json
QJsonObject jsonObject;
jsonObject.insert("dcode", "code");
jsonObject.insert("ver", "version");
//json QByteArray
QString strJson = QString(QJsonDocument(jsonObject).toJson(QJsonDocument::Compact));
QByteArray byte_json = strJson.toLocal8Bit();
request.setUrl(QUrl("http://qt-project.org"));//
// json , header
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));
if (m_Reply != Q_NULLPTR) {
m_Reply->deleteLater();
}
m_Reply = manager->post(request, byte_json);
QEventLoop loop;// ,
QTimer timer;
connect(m_Reply, SIGNAL(finished()), &loop, SLOT(quit()));
QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
timer.start(5000);// 5s
loop.exec(QEventLoop::ExcludeUserInputEvents);
if (m_Reply->error() == QNetworkReply::NoError){
QByteArray strJsonText = m_Reply->readAll();//
}
1.1. QNetworkRequest
도움말 문서 보기:http://doc.qt.io/qt-5/qnetworkrequest.html
주로 이 몇 가지 쓰기 방법 으로 각각 요청 한 종류 에 대해 설정 합 니 다.
클 라 이언 트 가 서버 에 HTTP 요청 메 시 지 를 보 내 는 것 은 다음 과 같은 형식 을 포함 합 니 다. 요청 줄 (request line), 요청 머리 (header), 빈 줄 과 요청 입 니 다. 데이터 네 부분 으로 구성 되 어 있 으 며, 아래 그림 은 요청 메시지 의 일반적인 형식 을 보 여 줍 니 다.요청 줄 구성: 요청 방법 + 스페이스 바 + url + 스페이스 바 + 프로 토 콜 버 전 + 리 턴 문자 + 줄 바 꿈 문자. 자세 한 내용 은 HTTP 메시지 구조 참조 header 에 대해 qt 는 매 거 진 형식 Known Headers 를 제공 하여 각각 다른 항목 을 표시 합 니 다.
Constant
Value
Description
QNetworkRequest::ContentDispositionHeader
6
Corresponds to the HTTP Content-Disposition header and contains a string containing the disposition type (for instance, attachment) and a parameter (for instance, filename).
QNetworkRequest::ContentTypeHeader
0
Corresponds to the HTTP Content-Type header and contains a string containing the media (MIME) type and any auxiliary data (for instance, charset).
QNetworkRequest::ContentLengthHeader
1
Corresponds to the HTTP Content-Length header and contains the length in bytes of the data transmitted.
QNetworkRequest::LocationHeader
2
Corresponds to the HTTP Location header and contains a URL representing the actual location of the data, including the destination URL in case of redirections.
QNetworkRequest::LastModifiedHeader
3
Corresponds to the HTTP Last-Modified header and contains a QDateTime representing the last modification date of the contents.
QNetworkRequest::CookieHeader
4
Corresponds to the HTTP Cookie header and contains a QList representing the cookies to be sent back to the server.
QNetworkRequest::SetCookieHeader
5
Corresponds to the HTTP Set-Cookie header and contains a QList representing the cookies sent by the server to be stored locally.
QNetworkRequest::UserAgentHeader
7
The User-Agent header sent by HTTP clients.
QNetworkRequest::ServerHeader
8
The Server header received by HTTP clients.
1.2. QNetworkReply
도움말 문서:http://doc.qt.io/qt-5/qnetworkreply.html
이러한 계승 은 QIODevice 에서 이 루어 집 니 다. 받 은 모든 정 보 를 읽 는 것 을 포함 하여 QIODevice 의 모든 인 터 페 이 스 를 사용 할 수 있 습 니 다.
이 동시에 finished 신 호 를 제공 합 니 다. 응답 완료 척후 에서 이 신 호 를 보 내 면 사용자 정의 슬롯 함수 와 관련 하여 응답 처 리 를 할 수 있 습 니 다.
attribute 속성 함 수 를 제공 하여 응답 유형 을 판단 할 수 있 습 니 다. 예 를 들 어 Redirection TargetAttribute 는 목표 url 알림 으로 방향 을 바 꿀 수 있 습 니 다.
QNetworkReply 는 자동 으로 공간 을 방출 하지 않 습 니 다. 메모리 방출 을 주동 적 으로 처리 해 야 합 니 다. QObject 를 호출 할 수 있 습 니 다.: deleteLater 는 자동 으로 공간 을 방출 하도록 합 니 다.
connect(m_reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(onDownloadProgress(qint64, qint64)));
connect(m_reply, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
connect(m_reply, SIGNAL(finished()), this, SLOT(onFinished()));
connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError)));
다운로드 요청 시:
onDownloadProgress(qint64, qint64);다운로드 진 도 를 표시 합 니 다. 매개 변수 1 과 2 는 각각 이번 다운로드 바이트 수 와 파일 총 바이트 크기 를 대표 합 니 다.
onReadyRead();다운로드 과정 에서 서버 에서 데 이 터 를 읽 기 시 작 했 습 니 다. 데 이 터 를 읽 고 로 컬 파일 에 기록 하 는 데 사용 되 며 데이터 추가 방식 으로 정지점 의 전송 을 편리 하 게 합 니 다.
void xx::onReadyRead()
{
if (m_reply == NULL) return;
QFile file(m_fileName);//
if (file.open(QIODevice::WriteOnly | QIODevice::Append))
{
file.write(m_reply->readAll());
}
file.close();
}
onFinished (): 다운로드 완료 이벤트.
onError (): 오류 이벤트 다운로드
2. 진행 표시 줄 다운로드, 일시 정지 지원, 정지 기능 QNetworkAccessManager 는 get 방법 으로 요청 을 보 내 고 QNetworkReply 로 되 돌려 받 습 니 다.QNetworkReply 는 다운로드 할 때마다 데이터 의 크기 와 파일 의 총 크기 를 피드백 하기 위해 다운로드 프로 세 스 신 호 를 사용 합 니 다. 2.1 readyRead() QNetworkReply 의 부모 클래스 QIODevice 가 제공 하 는 다운로드 과정 에서 의 신호 로, 이 신호 에 다운로드 파일 크기 를 기록 할 수 있 습 니 다. 2.2 downloadProgress(qint64 bytesReceived, qint64 bytesTotal) bytes Received 는 매번 파일 을 다운로드 할 때마다 바이트 크기 를 나타 내 고 bytes Total 은 다운로드 파일 바이트 의 총 크기 를 나타 낸다.
// ;
QString sValue = QString("%1").arg(bytesReceived * 100 / (bytesTotal));// , 100
ui.progressBar->setValue(sValue.toInt());
2.3 일시 정지 및 정지 기능 요점: QNetworkReply 의 신호 와 슬롯 을 풀 고 QNetworkReply 의 abort 방법 과 DeleteLater () 방법 을 호출 해 야 합 니 다.
disconnect(m_reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(onDownloadProgress(qint64, qint64)));
disconnect(m_reply, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
disconnect(m_reply, SIGNAL(finished()), this, SLOT(onFinished()));
disconnect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError)));
m_reply->abort();
m_reply->deleteLater();
m_reply = NULL;
3. 다운로드 / 남 은 크기, 남 은 시간, 다운로드 속도 표시 남 은 크기, 남 은 시간, 다운로드 속 도 를 계산 하려 면 다운로드 과정 에서 매번 다운로드 바이트 수 와 총 다운로드 바이트 수 에 따라 계산 해 야 하기 때문에 download Progress (qint 64 bytes Received, qint 64 bytes Total) 응답 하 는 슬롯 함수 에서 계산 합 니 다.
// MB/ MB
QString strDownCurrent = QStringLiteral(" :%1/%2").arg(transformUnit(m_currentDownload)).arg(transformUnit(bytesTotal));
ui.lb_size->setText(strDownCurrent);
//
qint64 ispeed = m_intervalDownload * 1000 / (timeNow - m_timeInterval);
qint64 timeRemain = (bytesTotal - bytesReceived) / ispeed;
QString strRemaind = QStringLiteral(" :%1").arg(transformTime(timeRemain));
ui.lb_remaind->setText(strRemaind);
//
QString strSpeed = QStringLiteral(" :%1").arg(transformUnit(ispeed, true));
ui.lb_rate->setText(strSpeed);
4. 다 중 스 레 드 다운로드, 인터페이스 스 레 드 차단 없 음 여기 에는 두 가지 방법 이 있 습 니 다. 하 나 는 MoveToThread 방법 을 통 해 하나의 계승 과 QObject 의 기능 류 를 통 해 이 루어 집 니 다. 두 번 째 는 QThread 를 계승 하고 QThread 를 통 해 다 중 스 레 드 를 실현 하 는 것 입 니 다. 저 는 두 번 째 를 사용 하여 계승 과 QThread 의 중간 류 를 제공 한 적 이 있 습 니 다. 다운로드 단 추 를 누 르 면 다운로드 스 레 드 를 시작 합 니 다:
m_strTargetAddress = "d:/Qt_Download.zip";//
QString strUrl = ui.lineEdit->text();//
if (m_pDownloadThread != NULL )
{
m_pDownloadThread->start();
}
5. 파일 정지점 리 셋 다운로드 5.1 정지점 전송 과 관련 하여 QNetworkRequest 는 요청 한 바이트 크기 와 너 비 를 설정 하 는 방법 SetRawHeader 와 "Range" 필드 를 제공 합 니 다. HTTP 프로 토 콜 요청 에서 파일 의 한 위치 에서 데 이 터 를 받 아들 이려 면 Range 머리 를 더 해 야 합 니 다. Range 머리의 형식 은 다음 과 같 습 니 다. 첫 500 바이트: bytes = 0 - 499 두 번 째 500 바이트: bytes = 500 - 999 마지막 500 바이트 표시: bytes = - 500 500 바이트 이후 의 범 위 를 나타 낸다: bytes = 500 - 첫 번 째 와 마지막 바이트: bytes = 0 - 0, - 1 동시에 몇 가지 범 위 를 지정 합 니 다: bytes = 500 - 600, 601 - 999
Range 요청 을 보 낸 후 서버 는 Content - Range 머리 에서 현재 받 은 범위 와 파일 의 총 크기 를 되 돌려 줍 니 다. 예 를 들 어:
Content-Range: 0-499/22400
여기 서 0 - 499 는 현재 보 낸 데이터 의 범 위 를 말 하 는데 22400 은 파일 의 총 크기 이다.
5.2 정지점 전송 을 실현 하려 면 클 라 이언 트 만 이 안 되 고 서버 에 있 는 파일 도 정지점 전송 을 지원 해 야 한다. 즉, 정지점 다운로드 전송 을 진행 할 때 먼저 다운로드 파일 이 정지점 다운 로드 를 지원 하 는 지 판단 해 야 한다. windows 에서 파일 다운로드 지원 정지점 다운로드 지원 을 어떻게 판단 합 니까? 5.2.1 cmd 에서 curl 명령 에 - i 인자 와 요청 할 바이트 크기 를 추가 합 니 다.
eg: curl -i --range 0-9 http://sqdownb.onlinedown.net/down/55412_20161201034403.zip 반환 데이터 에 Content - Range 와 HTTP / 1.1 206 Partial Content 바이트 가 포함 되 어 있 습 니 다. 예 를 들 어 상기 명령 을 수행 할 때 반환 결 과 는 다음 과 같 습 니 다.
HTTP/1.1 206 Partial Content
Date: Wed, 01 Aug 2018 03:12:14 GMT
Content-Type: application/zip
Content-Length: 10
Last-Modified: Wed, 07 Dec 2016 10:13:32 GMT
Connection: keep-alive
ETag: "5847e0cc-78ac98"
Content-Range: bytes 0-9/7908504
Content - Range: bytes 0 - 9 / 7908504 에서 돌아 오 는 바이트 수 7908504 는 파일 의 총 바이트 크기 입 니 다.
HTTP/1.1 206 Partial Content 대표 상태 값 206 대표 정지점 다운로드 지원 그래서 이 링크 는 정지점 다운 로드 를 지원 하 는 Content - Range 와 HTTP / 1.1 206 Partial Content 바이트 가 있 는 곳 으로 되 돌아 갑 니 다.
5.2.2 Qt 코드 에 서 는 QNetworkRequest 를 통 해 'Range' 를 요청 하고, 반환 값 QNetworkReply 의 rawHeader ('Content - Range') 를 통 해 반환 값 이 있 는 지 확인 합 니 다.
bool xx::bSupportBreak(const QUrl &url)
{
QNetworkAccessManager manager;
QEventLoop loop;
QTimer timer;
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("Range", "bytes=0-9");
// , ;
QNetworkReply *reply = manager.get(request);
if (!reply) return false;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
timer.start(2000);
loop.exec(QEventLoop::ExcludeUserInputEvents);
if (reply->error() != QNetworkReply::NoError)
{
// ;
qDebug() << reply->errorString();
return false;
}
else if (!timer.isActive())
{
// , ;
qDebug() << "Request Timeout";
return false;
}
timer.stop();
QByteArray range = reply->rawHeader("Content-Range");
if (!QString::fromLocal8Bit(range).isEmpty())
return true;
return false;
}
6. 다운로드 요청 시간 초과 처리 Qt 5.8 에 서 는 QNetworkAccessManager 클래스 든 QNetworkRequest 클래스 든 시간 초과 메커니즘 을 제공 하지 않 기 때문에 스스로 계산 할 수 밖 에 없습니다. 다운 로드 를 시작 할 때 타 이 머 를 통 해 5s 마다 다운로드 바이트 의 변화 값 을 측정 합 니 다.
_timeOut->start(5000);
5s 내 에 변화 가 없 으 면 기본적으로 시간 초과, 시간 초과 의 원인 이 많다 는 것 을 설명 한다. 다운로드 과정 에서 네트워크 가 끊 기거 나 네트워크 연결 이 불안정 하고 네트워크 카드 가 비활성화 되 는 등 이다.타이머 시간 초과 이 벤트 를 통 해 네트워크 링크 가 있 는 지 순환 적 으로 확인 하고 네트워크 연결 이 있 으 면 계속 다운로드 하 며 반대로 다운로드 가 중단 되 었 습 니 다.이러한 장점 은 다운로드 가 완료 되 기 전에 네트워크 에 파동 이 발생 하면 전체 파일 의 다운로드 에 영향 을 주지 않 고 폴 링 을 통 해 다운로드 가 완 료 될 때 까지 하 는 것 이다. 그러나 여기 서 저 는 프로그램 이 무절제 하 게 연결 을 요청 하지 않도록 30 분 이 넘 으 면 프로그램 이 요청 을 끊 고 다운로드 하지 않 습 니 다.
void xx::handleTimeOut()
{
if (m_bytesDown != m_bytesReceived) {
m_bytesDown = m_bytesReceived;
}
else if (!m_bClickPause) {
//
if (m_reply != NULL)
{
stopDownload();
m_timeElapsed.start();
}
//30 (30 )
int nElapsed = m_timeElapsed.elapsed();
if (nElapsed >= 1 * 30 * 60 * 1000)
{
_timeOut->stop();
return;
}
//
bool bConnect = this->bSupportBreak(m_qStrUrl);
if (bConnect)
{
_timeOut->stop();
this->downloadFile(m_qStrUrl, m_qStrFilePath);
}
}
}
7. 데모 주소 기능 구현
환경 은 VS 2015 + win 10 64 위.
원본 코드 와 실행 가능 한 프로그램 다운로드 주 소 를 추가 하 는 동시에 컴 파일 에 성공 한 OpenSsl 의 32 비트 와 64 비트 파일 도 있 습 니 다.
https://download.csdn.net/download/whanjim19/10576909
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Qt로 문자와 이미지의 혼합 텍스트 그리기텍스트를 그리려면 QPainter::drawText 함수를 사용하지만 텍스트와 동시에 이미지 (아이콘 등)를 함께 그리기를 원합니다. QLabel와 QPushButton는 이미지와 텍스트를 표시하는 기능을 가지고 있...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.