![](/img/trans.png)
[英]Python server cgi.FieldStorage parsing 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定義中不存在灰色部分,因此FS27和FS34之間的大部分差異在於字符串(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']
作為概念驗證 ,這些是FS27和FS34返回的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.