将带有百分比编码的QUrl转换为字符串

时间:2014-06-21 16:27:35

标签: qt urlencode qstring qurl

我使用用户输入的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中不起作用... Web服务器响应不同(它返回了不同的页面)。很明显,QUrl :: fromPercentEncoding()不是一个干净的解决方案,因为它有效地改变了URL。我可以在上面的函数中创建两个QUrl对象...一个直接构造,一个使用fromPercentEncoding()构建,第一个用于QWebView,后者仅用于显示/匹配......但这看起来很荒谬。

3 个答案:

答案 0 :(得分:10)

结论

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

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

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

  

返回URL的人类可显示字符串表示。可以通过传递带选项的标志来自定义输出。   RemovePassword始终处于启用状态,因为密码永远不会出现   向用户显示。“

实际上它没有声称任何解码能力,这里的文件不清楚它的行为。但至少密码部分是真的。我在Gitorious:

上找到了一些线索
  

添加QUrl :: toDisplayString(),这是没有密码的toString()。并修复toString()的文档,其中说这是方法   用于向人类展示,而这从未如此。“


测试代码

为了辨别不同功能的解码能力。以下代码已在 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());

<强> P.S。 QUrl::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"%encoded )时:

[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" 

P.S。我也遇到了Ilya在评论中提到的错误:Percent Encoding doesn't seem to be working for '+' in QUrl


摘要

QUrl::toDisplayString的结果含糊不清。如文档所述,必须谨慎使用QUrl::FullyDecoded模式。无论您使用何种类型的网址,都可以QUrl::toEncode对其进行编码,并在必要时将其显示为QUrl::fromPercentEncoding

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


有用的资源

  1. RFC 3986(QUrl符合)
  2. Encode table
  3. Source of qurl.cpp on Gitorious

答案 1 :(得分:3)

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

答案 2 :(得分:2)

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

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

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

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