9

我使用用户输入的 URL 作为文本来初始化 QUrl 对象。稍后我想将 QUrl 转换回字符串以显示它并使用正则表达式检查它。只要用户不输入任何百分比编码的 URL,这就可以正常工作。

为什么以下示例代码不起作用?

qDebug() << QUrl("http://test.com/query?q=%2B%2Be%3Axyz%2Fen").toDisplayString(QUrl::FullyDecoded); 

它根本不解码任何百分比编码的字符。它应该打印"http://test.com/query?q=++e:xyz/en",但实际上打印"http://test.com/query?q=%2B%2Be%3Axyz%2Fen".

我还尝试了很多其他方法,例如 fromUserInput() 但我无法使代码在 Qt5.3 中正常工作。

有人可以解释我如何做到这一点以及为什么即使使用 QUrl::FullyDecoded 上述代码也不起作用(即显示解码的 URL)?

更新

得到 fromPercentEncoding() 提示后,我尝试了以下代码:

QUrl UrlFromUserInput(const QString& input)
{
   QByteArray latin = input.toLatin1();
   QByteArray utf8 = input.toUtf8();
   if (latin != utf8)
   {
      // URL string containing unicode characters (no percent encoding expected)
      return QUrl::fromUserInput(input);
   }
   else
   {
      // URL string containing ASCII characters only (assume possible %-encoding)
      return QUrl::fromUserInput(QUrl::fromPercentEncoding(input.toLatin1()));
   }
}

这允许用户输入 unicode URL 和百分比编码的 URL,并且可以对这两种 URL 进行解码以进行显示/匹配。但是,百分比编码的 URL 在 QWebView 中不起作用......网络服务器的响应不同(它返回了不同的页面)。所以很明显 QUrl::fromPercentEncoding() 不是一个干净的解决方案,因为它有效地改变了 URL。我可以在上述函数中创建两个 QUrl 对象……一个直接构造,一个使用 fromPercentEncoding() 构造,第一个用于 QWebView,后者仅用于显示/匹配……但这似乎很荒谬。

4

3 回答 3

17

#结论

我做了一些研究,到目前为止的结论是:荒谬的。

QUrl::fromPercentEncoding()是要走的路,OP在UPDATE部分所做的应该是标题中问题的公认答案。

我认为 Qt 的文档QUrl::toDisplayString有点误导:

返回 URL 的人类可显示的字符串表示形式。可以通过传递带有选项的标志来自定义输出。始终启用选项 RemovePassword,因为永远不应向用户显示密码。”

实际上它没有声称任何解码能力,这里的文档不清楚它的行为。但至少密码部分是正确的。我在Gitorious 上找到了一些线索:

添加 QUrl::toDisplayString(),它是没有密码的 toString()。并修复了 toString() 的文档,该文档说这是用于向人类显示的方法,而这从来都不是真的。”


#Test Code 为了辨别不同函数的解码能力。以下代码已在Qt 5.2.1上测试过(尚未在 Qt 5.3 上测试过!)

QString target(/*path*/);

QUrl url_path(target);
qDebug() << "[Original String]:" << target;
qDebug() << "--------------------------------------------------------------------";
qDebug() << "(QUrl::toEncoded)          :" << url_path.toEncoded(QUrl::FullyEncoded);
qDebug() << "(QUrl::url)                :" << url_path.url();
qDebug() << "(QUrl::toString)           :" << url_path.toString(); 
qDebug() << "(QUrl::toDisplayString)    :" << url_path.toDisplayString(QUrl::FullyDecoded);
qDebug() << "(QUrl::fromPercentEncoding):" << url_path.fromPercentEncoding(target.toUtf8());

PSQUrl::url只是 的同义词QUrl::toString


#输出 [案例1]:当目标路径= "%_%"测试编码的功能):

[Original String]: "%_%" 
-------------------------------------------------------------------- 
(QUrl::toEncoded)          : "%25_%25" 
(QUrl::url)                : "%25_%25" 
(QUrl::toString)           : "%25_%25" 
(QUrl::toDisplayString)    : "%25_%25" 
(QUrl::fromPercentEncoding): "%_%" 

【案例2】:当目标路径= "Meow !"测试编码的功能)时:

[Original String]: "Meow !" 
-------------------------------------------------------------------- 
(QUrl::toEncoded)          : "Meow%20!" 
(QUrl::url)                : "Meow !" 
(QUrl::toString)           : "Meow !" 
(QUrl::toDisplayString)    : "Meow%20!" // "Meow !" when using QUrl::PrettyDecoded mode
(QUrl::fromPercentEncoding): "Meow !" 

【案例3】:当目标路径= "Meow|!"测试编码的功能)时:

[Original String]: "Meow|!" 
-------------------------------------------------------------------- 
(QUrl::toEncoded)          : "Meow%7C!" 
(QUrl::url)                : "Meow%7C!" 
(QUrl::toString)           : "Meow%7C!" 
(QUrl::toDisplayString)    : "Meow|!" // "Meow%7C!" when using QUrl::PrettyDecoded mode
(QUrl::fromPercentEncoding): "Meow|!" 

【案例4】:当目标路径= "http://test.com/query?q=++e:xyz/en"无%编码)时:

[Original String]: "http://test.com/query?q=++e:xyz/en" 
-------------------------------------------------------------------- 
(QUrl::toEncoded)          : "http://test.com/query?q=++e:xyz/en" 
(QUrl::url)                : "http://test.com/query?q=++e:xyz/en" 
(QUrl::toString)           : "http://test.com/query?q=++e:xyz/en" 
(QUrl::toDisplayString)    : "http://test.com/query?q=++e:xyz/en" 
(QUrl::fromPercentEncoding): "http://test.com/query?q=++e:xyz/en" 

【案例5】:当目标路径= "http://test.com/query?q=%2B%2Be%3Axyz%2Fen"%编码)时:

[Original String]: "http://test.com/query?q=%2B%2Be%3Axyz%2Fen" 
-------------------------------------------------------------------- 
(QUrl::toEncoded)          : "http://test.com/query?q=%2B%2Be%3Axyz%2Fen" 
(QUrl::url)                : "http://test.com/query?q=%2B%2Be%3Axyz%2Fen" 
(QUrl::toString)           : "http://test.com/query?q=%2B%2Be%3Axyz%2Fen" 
(QUrl::toDisplayString)    : "http://test.com/query?q=%2B%2Be%3Axyz%2Fen" 
(QUrl::fromPercentEncoding): "http://test.com/query?q=++e:xyz/en" 

PS 我还遇到了 Ilya 在评论中提到的错误:百分比编码似乎不适用于 QUrl 中的 '+'


#概括

结果QUrl::toDisplayString是模棱两可的。正如文件所说,QUrl::FullyDecoded必须小心使用该模式。无论您获得哪种类型的 URL,都可以对它们进行编码并在必要时QUrl::toEncode显示它们。QUrl::fromPercentEncoding

至于QWebViewOP中提到的百分比编码URL的故障,需要更多的细节来调试它。不同的功能和不同的使用模式可能是原因。


#有用的资源

  1. RFC 3986(符合 QUrl)
  2. 编码表
  3. Gitorious 上 qurl.cpp 的来源
于 2014-06-24T19:05:13.397 回答
3

我不确定为什么toDisplayString(QUrl::FullyDecoded)不起作用。

在尝试了几个版本后,我发现copy.query(QUrl::FullyDecoded)确实可以解码查询部分。文档有一个示例,以下代码确实返回了解码后的 URL :

QUrl url("http://test.com/query?q=%2B%2Be%3Axyz%2Fen");
url.setQuery(url.query(QUrl::FullyDecoded), QUrl::DecodedMode);
qDebug() << url.toString();

以这种方式解决问题并不是最优的,因为查询部分是在不需要的情况下复制的。

于 2014-06-24T08:25:12.853 回答
3

您可以使用QUrlQuery::toString(QUrl::FullyEncoded)QUrl::fromPercentEncoding()进行此转换。

于 2014-06-21T16:37:17.383 回答