使用Qt进行Http download时,需注意一点,安卓下载URL为https时会报错,需要支持SSL。

头文件downfile.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#ifndef DOWNFILE_H
#define DOWNFILE_H

#include <QFile>
#include <QtNetwork/QNetworkAccessManager> //文件下载
#include <QNetworkReply>
#include <QMutex>
#include <QSharedPointer>

#pragma pack(1)

struct UPDATE_HEADER
{
uint16_t project_id; /**< each project has its unique id */
uint8_t root_version; /**<secondary boot update*/
uint8_t stack_version; /**<stack update*/
uint32_t app_version; /**<app update*/
uint32_t code_size; /**< updated code size*/
uint32_t crc32; /**<crc32*/
} ;

struct pk_t
{
uint32_t addr;
uint16_t pk;
};
#pragma pack()

extern pk_t pt;
extern UPDATE_HEADER ota_vs_info;

class DownFile : public QObject
{
Q_OBJECT
public:
static DownFile *getInstance();
private:
DownFile();
DownFile& operator=(DownFile&) = delete;
DownFile(DownFile&) = delete;

private:
static DownFile *downFile;
static QMutex m_mutex;
private:
QFile *avatorFile;
QNetworkReply *avatorReply;
QNetworkAccessManager *avatorManager;

public:
int ota_size;
uint8_t ota_data[40*1024];
private:
QString fileName;
QString downUrl = "http://qzwjer.top/doc/";
private:
void copyfile();

private slots:
void httpDownload();
void httpDownloadFinished();

public:
void setUrl(const QString &);
QString& getUrl();
void setFileName(const QString &);
void getfile();

signals:
void downComplete();
};

#endif //

downfile.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include "downfile.h"
#include <QDebug>
#include <QDataStream>
#include <QFileInfo>
#include <QDir>
#include <QUrl>

#pragma execution_character_set("utf-8")

pk_t pt = {0};
UPDATE_HEADER ota_vs_info = {0};

#ifdef Q_OS_ANDROID
static QString path = "file:///storage/emulated/0/BMTest/otafile/";
static QString fpath = QUrl(path).toLocalFile();
#else
static QString fpath = "otafile/";
#endif


DownFile* DownFile::downFile = nullptr;
QMutex DownFile::m_mutex;

DownFile *DownFile::getInstance()
{
if(nullptr == downFile){
m_mutex.lock();
if(nullptr == downFile){
downFile = new DownFile;
}
m_mutex.unlock();
}
return downFile;
}

DownFile::DownFile()
{
qDebug()<<fpath;
}

void DownFile::copyfile()
{
QFile file(fpath + fileName);
if(!file.open(QIODevice::ReadOnly))
{
qDebug()<<"file open error!";
}
else
{
memset(ota_data, 0, sizeof(ota_data));
ota_size = file.size();
QDataStream in(&file);
while(!in.atEnd())
{
in.readRawData((char*)ota_data, sizeof(ota_data));
}

#if 1
QString str;
for(int i = 0; i < 16; i++)
{
str += QString::asprintf("%02x ", ota_data[i]);
}
qDebug()<<"ota_head:"<<str;
#endif
//对文件头做判断

memcpy(&ota_vs_info, ota_data, sizeof(UPDATE_HEADER));
emit downComplete();
}
}

void DownFile::httpDownload()
{
//NOTE : 为什么安卓不行 ==> https->http
#ifdef Q_OS_ANDROID
QByteArray ba = avatorReply->readAll();
memcpy(&ota_data[ota_size], ba.data(), ba.length());
ota_size += ba.length();
#else
#if 1
if(avatorFile){
avatorFile->write(avatorReply->readAll());
}
#else
QTextStream out(avatorFile);
out<<avatorReply->readAll();
#endif
#endif
}

void DownFile::httpDownloadFinished()
{
//刷新文件
#ifndef Q_OS_ANDROID
avatorFile->flush();
avatorFile->close();
delete avatorFile;
avatorFile=0;
#endif
qDebug()<<avatorReply->error();
if(avatorReply->error() != QNetworkReply::NoError)
{
qDebug()<<"download failed";
}
else
{
qDebug()<<"download finished";
#ifndef Q_OS_ANDROID
copyfile();
#else
memcpy(&ota_vs_info, ota_data, sizeof(UPDATE_HEADER));
emit downComplete();
#endif
}
delete avatorManager;
avatorManager = nullptr;
}

void DownFile::setUrl(const QString &url)
{
downUrl = url;
}

QString &DownFile::getUrl()
{
return downUrl;
}

void DownFile::setFileName(const QString &name)
{
fileName = name;
}

void DownFile::getfile()
{
QDir dir;
bool ota_down_flag = false;
ota_size = 0;
#ifndef Q_OS_ANDROID
QString ota_file = fpath + fileName;
QFileInfo fileInfo(ota_file);
if(fileInfo.isFile())
{
ota_down_flag = true;
qDebug()<<"本地文件";
copyfile();
}
else if(!dir.exists(fpath))
{
dir.mkpath(fpath);
}
#endif
if(!ota_down_flag)
{
#ifndef Q_OS_ANDROID
avatorFile = new QFile(ota_file);
if(!avatorFile->open(QIODevice::WriteOnly)) {
delete avatorFile;
avatorFile=0;
qDebug()<<"can not write ota file";
return;
}
#endif
//开始请求 下载文件
qDebug()<<downUrl + fileName;
QUrl serviceUrl = QUrl(downUrl + fileName);
//get方式请求 如需加密用post
avatorManager = new QNetworkAccessManager(this);
avatorReply=avatorManager->get(QNetworkRequest(serviceUrl));
connect(avatorReply,SIGNAL(readyRead()),this,SLOT(httpDownload()));
connect(avatorReply,SIGNAL(finished()),this,SLOT(httpDownloadFinished()));
}
}