POST请求时表单参数名需要编码吗?

0 投票
2 回答
902 浏览
提问于 2025-04-16 07:57

简短版本:使用标准的 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 个回答

1

虽然这个问题本质上已经有了答案,但我想提供一些关于如何深入了解这些RFC文档的更多细节。

RFC 2388的第3节提到需要一个Content-Disposition头。对于非ASCII的数据,应该使用RFC 2047进行编码,尽管这看起来有点矛盾RFC 2183的第2节描述了这个Content-Disposition头的格式。name符合一般的parameter规则,但它引用了RFC 2045。在第5.1节中,你会发现parameter的右侧可以是tokenquoted-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字段名称的问题让我今天关注到你的这个问题。

1

RFC 2388 讲的是如何处理多部分表单数据的提交。第3节说明,参数名称应该是ASCII字符,或者按照RFC 2047的规定进行编码。

所以,如果你的POST请求是以multipart/form-data格式编码的(就像提问者所做的那样),那么参数名称就不需要这样编码。我建议你可以向作者反馈这个问题(咳咳...),他可能会在未来的版本中修复这个问题;)

一个解决方法是直接设置你的MultipartParam的名称属性,比如:

   p.name = 'file[]'

撰写回答