【问题标题】:Qt does not encode '+' signQt 不编码“+”号
【发布时间】:2018-05-25 04:48:00
【问题描述】:

为什么 Qt5 不将加号编码为 %2B?

我试过这段代码:

QUrlQuery urlQuery;
urlQuery.addQueryItem("test", "hello+world");
manager->post(request, urlQuery.toString(QUrl::FullyEncoded).toUtf8());

但在服务器端,我总是得到如下字符串:

hello world

没有 %2B 也没有加号。所以我无法在服务器端获得“+”号...

如何使用 Qt5 发送加号?

【问题讨论】:

标签: qt encoding


【解决方案1】:

如何使用 Qt5 发送加号?

不要为post 数据使用网址,请使用QByteArray。它将按原样发送。

编辑

QUrlQuery 的附加信息,+ 号是一种特殊情况(来自文档):

处理空格和加号(“+”)

Web 浏览器通常将 HTML FORM 元素中的空格编码为 加号 ("+") 和加号为其百分比编码形式 (%2B)。 但是,管理 URL 的 Internet 规范并未考虑 空格和加号字符等效。因此,QUrlQuery 永远不会将空格字符编码为“+”,也永远不会将“+”解码为 一个空格字符。相反,空格字符将在 编码形式。为了支持 HTML 表单的编码,QUrlQuery 也从不将“%2B”序列解码为加号,也不编码加号 符号。事实上,在键、值、 或查询字符串与所写的完全一样(除了 将“%2b”大写为“%2B”)。

因此,如果您想对包含 + 符号的字符串使用 QUrlQuery,似乎您必须自己进行编码("+" => "%2B"),您可以使用静态方法 QUrl::toPercentEncoding()

【讨论】:

  • 你说的我试过了。 QByteArray dataToSend("POSTDATA=hello+world"); manager->post(request, dataToSend); 在服务器端我得到:POSTDATA: hello world 再次没有加号。
  • @Mike 你是怎么定义ContentTypeHeader的,是“application/Json”吗?如果是 Json,您能否使用 QJsonDocument.toJson() 在有效的 Json 文档中发送您的数据?
  • 我使用request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); 否则我无法将带有参数的帖子数据发送到服务器。
  • @Mike。哦,我明白了,让我检查一下。
  • 只有我一个人...是qt的bug吗?为什么要对其他符号进行编码?
【解决方案2】:

使用 PyQt 5 和 Python 2.7,尽管本页其他地方的 Ilya 提供了有用的 answer,但我还是有点难以弄清楚。

这就是最终对我有用的方法(OP 的示例转换为 Python2.7/PyQt5):

url_query = QUrlQuery()
url_query.addQueryItem('test', str(QtCore.QUrl.toPercentEncoding('hello+world')))
manager.post(request, str(url_query.toString(QUrl.FullyEncoded)))

这是一个使用httpbin.org检查发布内容的完整示例:

import sys
import json
from PyQt5 import QtCore, QtWidgets, QtNetwork


def slot_finished(reply):
    """ Get form data from reply content """
    reply_content = json.loads(str(reply.readAll()))
    print 'returned: {}'.format(reply_content['form'][KEY])


# Some variables
url = u'http://httpbin.org/post'
content_type = u'application/x-www-form-urlencoded'
KEY = 'test'
data = u'hello + world'

# Build content for the request
url_query = QtCore.QUrlQuery()
url_query.addQueryItem(KEY, str(QtCore.QUrl.toPercentEncoding(data)))
content = str(url_query.toString(QtCore.QUrl.FullyEncoded))

# Post the request and show the reply content
app = QtWidgets.QApplication(sys.argv)
manager = QtNetwork.QNetworkAccessManager()
manager.finished.connect(slot_finished)
manager.finished.connect(app.quit)  # relies on connection order
request = QtNetwork.QNetworkRequest(QtCore.QUrl(url))
request.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader, content_type)
reply = manager.post(request, content)
print 'expected: {}'.format(data)
app.exec_()

注意:不知道为什么,但该示例似乎也可以在没有明确设置QtCore.QUrl.FullyEncoded 的情况下工作。以下是 Qt docs 对该常量的看法:

将所有字符保留为正确编码的形式,作为这个组件 将作为 URL 的一部分出现。当与 toString() 一起使用时,这 以 QString 形式生成一个完全兼容的 URL,完全等于 toEncoded() 的结果

【讨论】:

    猜你喜欢
    • 2013-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多