簡體   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