POST请求时表单参数名需要编码吗?
简短版本:使用标准的 multipart/form-data 编码发送的“表单”参数名称需要编码吗?
详细版本:在 1fichier.com 这个上传大文件的服务上,上传表单是这样指定要上传的文件参数的:
<input type="file" name="file[]" size="50" title="Select the files to upload" />
这个参数的名称是 file[](注意有方括号)。
通过 LiveHTTPHeaders,我看到在 Firefox 中提交表单时,这个参数是这样发送的(也就是带有方括号)。但是,对于我正在用 Python 编写的一个 程序,我使用 poster 模块来上传文件,采用标准的 multipart/form-data 编码。如果我输入带方括号的参数名称,它会被发送成这样:
file%5B%5D
在内部,poster 使用这个函数来编码参数名称:
def encode_and_quote(data):
"""If ``data`` is unicode, return urllib.quote_plus(data.encode("utf-8"))
otherwise return urllib.quote_plus(data)"""
if data is None:
return None
if isinstance(data, unicode):
data = data.encode("utf-8")
return urllib.quote_plus(data)
urllib.quote_plus 的文档说,这个编码只在构建要放入 URL 的查询字符串时需要“对 HTML 表单值进行编码”。但在这里我们是做 POST 请求,所以表单值并不放在 URL 中。
那么,这些参数名称还需要编码吗,还是说 poster 这样做是错误的?
2 个回答
虽然这个问题本质上已经有了答案,但我想提供一些关于如何深入了解这些RFC文档的更多细节。
RFC 2388的第3节提到需要一个Content-Disposition头。对于非ASCII的数据,应该使用RFC 2047进行编码,尽管这看起来有点矛盾。RFC 2183的第2节描述了这个Content-Disposition头的格式。name
符合一般的parameter
规则,但它引用了RFC 2045。在第5.1节中,你会发现parameter
的右侧可以是token
或quoted-string
。这两种格式都没有提到表单名称的URL编码格式。不过[
和]
属于tspecials
,所以它们不能作为token
的一部分。因此我们得到了
Content-Disposition: form-data; name="file[]" (correct)
Content-Disposition: form-data; name=file[] (invalid)
Content-Disposition: form-data; name="file%5B%5D" (wrong name)
Content-Disposition: form-data; name=file%5B%5D (wrong name)
还有一点要注意的是非ASCII文件名:当前的HTML 5规范草案要求不以7位安全的方式进行编码,而是以请求中使用的编码进行传输。关于非ASCII字段名称的问题让我今天关注到你的这个问题。