看了看電腦右上角的時間,2017就要徹底流逝了。再瞅了瞅本月的文章數,天啦,隻有一篇,近一個月沒有時間學習,沒有時間寫文章,沒有時間休息,總之就是沒時間……好強烈的罪惡感,趕緊抓住最後的幾個小時,補上一文!
我們知道簡單的HTTP請求可以一次傳回結果,但對于一些資料量較大的情況,則要分多次傳回。
QNetworkAccessManager下的QNetworkReply有readyRead信号,一旦該信号産生,就可以讀取相應的資料并寫入檔案中。
對于較大的檔案,比如圖檔,一個http請求需要分多個資料包傳回結果最後才能得到完整的集合。
好在有QNetworkReply::finished。該信号提示我們不會再有資料更新了,此時就可以關閉檔案流,結束資料存儲。
如下:
new QNetworkRequest ();
manager = new QNetworkAccessManager(this);
request->setUrl(QUrl("https://static.baydn.com/static/img/icon_head.png"));
reply = manager->get(*request);
connect(reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotError(QNetworkReply::NetworkError)));
// SSL(Secure Sockets Layer 安全套接層), it encrypts data.
connect(reply, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(slotSslErrors(QList<QSslError>)));
connect(reply, SIGNAL(finished()), this, SLOT(slotFinished()));
資料存儲函數:
void HttpManager::slotReadyRead()
{
static int time = 0;
QByteArray bytes = reply->readAll();
QString url = reply->request().url().toString();
int fd;
if(searchFilesMap(url.toStdString())){ //if fd exist, we append data to local file.
fd = filesMap[url.toStdString()];
size_t ret = write(fd, bytes.toStdString().c_str(), bytes.size());
if(ret <= 0){
LOGDBG("write failed: %s", strerror(errno));
}
}
else { //if not exist, we. open and write.
string path = getIncomLocalPicPath(url.toStdString());
fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC);
if(fd == -1){
LOGDBG("open failed, %s",strerror(errno));
return ;
}
fchmod(fd, 0777);
size_t ret = write(fd, bytes.toStdString().c_str(), bytes.size());
if(ret <= 0){
LOGDBG("write failed: %s", strerror(errno));
}
// add info to map
filesMap[url.toStdString()] = fd;
}
LOGDBG("%d finished, fd: %d, url: %s",++time, fd, reply->request().url().toString().toStdString().c_str());
}
結束函數:
關閉句柄并重命名。
void HttpManager::slotFinished()
{
QString url = reply->request().url().toString();
QByteArray bytes = reply->readAll();
int fd = filesMap[url.toStdString()];
close(fd);
string f1;
string f2;
f1 = getIncomLocalPicPath(url.toStdString());
f2 = getComLocalPicPath(url.toStdString());
if(0 != rename(f1.c_str(),f2.c_str())){
LOGDBG("rename failed: %s", strerror(errno));
}
LOGDBG("%d, finished.", fd);
$ ./http_test
[file: httpmanager.cpp, line: 152, funcName: slotReadyRead] 1 finished, fd: 19, url: https://static.baydn.com/static/img/icon_head.png
[file: httpmanager.cpp, line: 152, funcName: slotReadyRead] 2 finished, fd: 19, url: https://static.baydn.com/static/img/icon_head.png
[file: httpmanager.cpp, line: 152, funcName: slotReadyRead] 3 finished, fd: 19, url: https://static.baydn.com/static/img/icon_head.png
[file: httpmanager.cpp, line: 152, funcName: slotReadyRead] 4 finished, fd: 19, url: https://static.baydn.com/static/img/icon_head.png
[file: httpmanager.cpp, line: 152, funcName: slotReadyRead] 5 finished, fd: 19, url: https://static.baydn.com/static/img/icon_head.png
[file: httpmanager.cpp, line: 181, funcName: slotFinished] 19, finished.