介绍
记录下之前Qt做的解析Http和Https的文件信息的过程。
思路
Qt这边已经提供了Network给我们解析,所以不是特殊的话,没必要再去找其他库来解决。主要思路是发送请求后,等待触发解析结束的信号,然后接收这个信号去解析里面的内容。
同时要获取文件名的话,会有多种情况要去解析。
1、网页里面已经写好了Content-Disposition,那么可以直接解析出这个字段来获取filename。
2、没有Content-Disposition,那么就去获取它的basename。
3、还需要考虑到多级跳转情况,这个时候要跳转多次才能获取到Disposition或者真正目标地址的basename。
4、下面代码只供思路参考,用的时候不建议直接copy。
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
//....省略....
protected:
QNetworkAccessManager m_manager; // 发送请求和接收应答
QNetworkRequest m_request; // 保存准备发送的请求
QNetworkReply *m_reply; // 接收到的应答
QUrl m_url; // 要解析的地址
QString m_strFileName; // 存放解析出来的文件名
QString m_strFileSize; // 存放解析出来的文件的大小
/**
* @brief Parse2FileName 解析Url,该操作是异步
* @param url 要解析的地址
*/
void ParseFileInfo(std::string url);
private slots:
void OnGetHeaders();
void XXXX::ParseFileInfo(std::string url)
{
m_strFileName = "";
m_strFileSize = "";
m_url = QUrl::fromUserInput(QString(url.c_str()));
m_request.setUrl(m_url);
m_reply = m_manager.head(m_request); // 解析头
connect(m_reply, &QNetworkReply::finished, this, &ParseUrl::OnGetHeaders); // 等待结束
}
void XXXX::OnGetHeaders()
{
if(m_reply->hasRawHeader("Content-Disposition"))
{
QString strFileName = m_reply->rawHeader("Content-Disposition");
int idx = strFileName.indexOf(QStringLiteral("filename="));
if(idx >= 0) //找到filename字段
{
strFileName = strFileName.replace('"', ""); //filename=后面有双引号,应该全部删除
strFileName = strFileName.mid(idx + 9);
m_strFileName = strFileName;
}
}
else //如果没有Content-Disposition,则用QUrl获取basename
{
m_url = m_reply->url();
if(!m_url.isEmpty())
{
m_strFileName = m_url.fileName();
}
}
if(m_reply->hasRawHeader("Content-Length"))
{
QString strFileSize = m_reply->rawHeader("Content-Length");
m_strFileSize = strFileSize;
}
else
{
m_strFileSize = "0";
}
}
上面这样,就能获取到没有跳转的http的文件信息了。但是如果出现多级跳转的话,是无法正确拿到的。这边有两个做法:
1、如果解析出来的header里面有location,那么就套娃解析,直到没有,然后再去取文件名。
2、初始化request时候,设置request属性,让request自己帮我们跳转。
m_request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
采用这两种方法,碰到跳转的链接时候,都能正确拿到URL。
注意点
但是如果去解析https的话,很多人此时会报SSL的错。一般情况下是Qt安装目录下少了对应的DLL。
这时候根据你的客户端(32或者64位),去安装对应位数的OpenSSL,然后去OpenSSL的目录下,将目录下的库移到Qt对应编译器的下面,这步骤可以百度,因为Qt版本不同和编译器不同处理方法也不同,就不转载了。
qDebug() << QSslSocket::supportsSsl() << QSslSocket::sslLibraryBuildVersionString() << QSslSocket::sslLibraryVersionString();
可以事先打印这句话,如果是false那就是不支持https的,如果是true,那么解析https一般就没问题了。当然这是我自己遇到的情况,不是适合所有人。
不对的地方或者有更好的方法欢迎评论指正,也希望这部分代码能帮助到需要的人。