繁体   English   中英

使用cgi.FieldStorage解析multipart / form-data; 无钥匙

[英]Parse multipart/form-data using cgi.FieldStorage; None keys

以下代码应该能够在Python 2.7和Python 3.x中运行。

from __future__ import unicode_literals
from __future__ import print_function

import cgi
try:
    from StringIO import StringIO as IO
except ImportError:
    from io import BytesIO as IO

body = """
--spam
Content-Disposition: form-data; name="param1"; filename=blob
Content-Type: binary/octet-stream

value1
--spam--
"""

parsed = cgi.FieldStorage(
    IO(body.encode('utf-8')),
    headers={'content-type': 'multipart/form-data; boundary=spam'},
    environ={'REQUEST_METHOD': 'POST'})

print([key for key in parsed])

在Python 2.7中它运行正常并输出['param1'] 但是在Python 3.4中,它输出[None]

我无法让FieldStorage在Python 3中获得可用的结果。我怀疑内部发生了一些变化,我现在正在使用它。 但是我似乎无法弄清楚是什么。 任何帮助表示赞赏。

这些更改将使您的脚本在Python 2.7.x和3.4.x中的工作方式完全相同:

(我将使用cgi.FieldStorage()这些缩写:Python 2.7.x: FS27 ,Python 3.4.x: FS34

1 -虽然FS27边界之前正确处理新行,就是不与FS34的情况下,这样的解决方案是先从你的边界( spam直接)。

body = """--spam
Content-Disposition: form-data; name="param1"; filename=blob
Content-type: binary/octet-stream

value1
--spam--
"""

2 - 从cgi.py 引用(在FS34的定义注释中):

参数,全部可选:

fp:文件指针; default:sys.stdin.buffer(请求方法为GET时不使用)

  Can be : 1. a TextIOWrapper object 2. an object whose read() and readline() methods return bytes 

FS27定义中不存在灰色部分,因此FS27FS34之间的大部分差异在于字符串(FS27)二进制流(FS34)的处理

在这种情况下, FS34很容易混淆解析对象的语义,除非给出正确处理方法的正确指示。 显然, headers字典条目'content-type': 'multipart/form-data; boundary=spam' 'content-type': 'multipart/form-data; boundary=spam'还不够; 你必须提供消息长度信息。

您可以通过在headers添加第二个条目来有效地实现此目的:

headers={'content-type': 'multipart/form-data; boundary=spam;',
'content-length': len(body)}

其中content-length body长(包括起始/结束边界)。


这些修改结合起来,产生了预期的结果:

$ python script.py
['param1']
$ python3 script.py
['param1']

作为概念验证 ,这些是FS27FS34返回的parsed对象:

...
print(parsed)
...

收益率:

FieldStorage(None, None, [FieldStorage('param1', 'blob', 'value1')])

对于FS27 ,和

FieldStorage(None, None, [FieldStorage('param1', 'blob', b'value1')])

对于FS34

在Python 2.7和Python 3.5中(由于某种原因在Python 3.4中不起作用),通过向响应主体添加Content-Length来返回所需的输出:

body = """
--spam
Content-Disposition: form-data; name="param1"; filename=blob
Content-Length: 6
Content-Type: binary/octet-stream

value1
--spam--
"""

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM