使用 BaseHTTPRequestHandler 从 POST 请求接收二进制文件
receive binary file from POST request with BaseHTTPRequestHandler
我一直在试验 this forum 中的一些代码。到目前为止,它可以正常接收在 curl POST 请求中传送的 json 片段,但现在我正在尝试向它发送一个小的 .jpg 文件。它同时以多种方式失败,但我对这些问题中的第一个是如何出现的感到困惑。
我的代码如下所示:
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs
from cgi import parse_header, parse_multipart
class ReportHandler(BaseHTTPRequestHandler):
def do_HEAD(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
def parse_POST(self):
print(self.headers)
ctype, pdict = parse_header(self.headers['content-type'])
print("ctype", ctype, ctype == 'application/octet-stream')
print(pdict)
if ctype == 'multipart/form-data':
postvars = parse_multipart(self.rfile, pdict)
elif ctype == 'application/x-www-form-urlencoded' or 'application/json':
print("here!")
length = int(self.headers['content-length'])
postvars = parse_qs(
self.rfile.read(length).decode('utf8'),
keep_blank_values=1)
print(postvars)
elif ctype == 'application/octet-stream':
print("octet stream header")
else:
print("nothing")
postvars = {}
a = self.rfile
print(dir(a))
print(a.peek())
return postvars
def do_POST(self):
postvars = self.parse_POST()
print(postvars)
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def main():
server = HTTPServer(('', 8088), ReportHandler)
try:
print('Started http server')
server.serve_forever()
except KeyboardInterrupt:
print('^C received, shutting down server')
server.socket.close()
if __name__ == "__main__":
main()
然后我在另一个终端输入 curl 命令,如下所示:
curl --request POST -H "Content-Type:application/octet-stream" --data-binary "@test.jpg" http://127.0.0.1:8088
它返回以下输出和错误跟踪:
python receive_requests.py
Started http server
Host: 127.0.0.1:8088
User-Agent: curl/7.52.1
Accept: */*
Content-Type: application/octet-stream
Content-Length: 16687
Expect: 100-continue
ctype application/octet-stream True
{}
here!
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 52056)
Traceback (most recent call last):
File "/usr/local/lib/python3.6/socketserver.py", line 317, in _handle_request_noblock
self.process_request(request, client_address)
File "/usr/local/lib/python3.6/socketserver.py", line 348, in process_request
self.finish_request(request, client_address)
File "/usr/local/lib/python3.6/socketserver.py", line 361, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/local/lib/python3.6/socketserver.py", line 721, in __init__
self.handle()
File "/usr/local/lib/python3.6/http/server.py", line 418, in handle
self.handle_one_request()
File "/usr/local/lib/python3.6/http/server.py", line 406, in handle_one_request
method()
File "receive_requests.py", line 42, in do_POST
postvars = self.parse_POST()
File "receive_requests.py", line 27, in parse_POST
self.rfile.read(length).decode('utf8'),
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
----------------------------------------
所以编码有问题,但我真正想知道的是它是如何结束的:
elif ctype == 'application/x-www-form-urlencoded' or 'application/json':
..尽管
print("ctype", ctype, ctype == 'application/octet-stream')
给予
>>> ctype application/octet-stream True
如果有人知道如何修复此代码以便它接收二进制文件,请 post 它,否则它如何设法转到错误的 elif
选项?是否有关于 headers 或我缺少的 curl 行为的内容?
您的条件将始终 return 正确。非空字符串的计算结果为 True
:
elif ctype == 'application/x-www-form-urlencoded' or 'application/json':
应该是:
elif ctype == 'application/x-www-form-urlencoded' or ctype == 'application/json':
或
elif ctype in ('application/x-www-form-urlencoded', 'application/json'):
我一直在试验 this forum 中的一些代码。到目前为止,它可以正常接收在 curl POST 请求中传送的 json 片段,但现在我正在尝试向它发送一个小的 .jpg 文件。它同时以多种方式失败,但我对这些问题中的第一个是如何出现的感到困惑。
我的代码如下所示:
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs
from cgi import parse_header, parse_multipart
class ReportHandler(BaseHTTPRequestHandler):
def do_HEAD(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
def parse_POST(self):
print(self.headers)
ctype, pdict = parse_header(self.headers['content-type'])
print("ctype", ctype, ctype == 'application/octet-stream')
print(pdict)
if ctype == 'multipart/form-data':
postvars = parse_multipart(self.rfile, pdict)
elif ctype == 'application/x-www-form-urlencoded' or 'application/json':
print("here!")
length = int(self.headers['content-length'])
postvars = parse_qs(
self.rfile.read(length).decode('utf8'),
keep_blank_values=1)
print(postvars)
elif ctype == 'application/octet-stream':
print("octet stream header")
else:
print("nothing")
postvars = {}
a = self.rfile
print(dir(a))
print(a.peek())
return postvars
def do_POST(self):
postvars = self.parse_POST()
print(postvars)
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def main():
server = HTTPServer(('', 8088), ReportHandler)
try:
print('Started http server')
server.serve_forever()
except KeyboardInterrupt:
print('^C received, shutting down server')
server.socket.close()
if __name__ == "__main__":
main()
然后我在另一个终端输入 curl 命令,如下所示:
curl --request POST -H "Content-Type:application/octet-stream" --data-binary "@test.jpg" http://127.0.0.1:8088
它返回以下输出和错误跟踪:
python receive_requests.py
Started http server
Host: 127.0.0.1:8088
User-Agent: curl/7.52.1
Accept: */*
Content-Type: application/octet-stream
Content-Length: 16687
Expect: 100-continue
ctype application/octet-stream True
{}
here!
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 52056)
Traceback (most recent call last):
File "/usr/local/lib/python3.6/socketserver.py", line 317, in _handle_request_noblock
self.process_request(request, client_address)
File "/usr/local/lib/python3.6/socketserver.py", line 348, in process_request
self.finish_request(request, client_address)
File "/usr/local/lib/python3.6/socketserver.py", line 361, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/local/lib/python3.6/socketserver.py", line 721, in __init__
self.handle()
File "/usr/local/lib/python3.6/http/server.py", line 418, in handle
self.handle_one_request()
File "/usr/local/lib/python3.6/http/server.py", line 406, in handle_one_request
method()
File "receive_requests.py", line 42, in do_POST
postvars = self.parse_POST()
File "receive_requests.py", line 27, in parse_POST
self.rfile.read(length).decode('utf8'),
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
----------------------------------------
所以编码有问题,但我真正想知道的是它是如何结束的:
elif ctype == 'application/x-www-form-urlencoded' or 'application/json':
..尽管
print("ctype", ctype, ctype == 'application/octet-stream')
给予
>>> ctype application/octet-stream True
如果有人知道如何修复此代码以便它接收二进制文件,请 post 它,否则它如何设法转到错误的 elif
选项?是否有关于 headers 或我缺少的 curl 行为的内容?
您的条件将始终 return 正确。非空字符串的计算结果为 True
:
elif ctype == 'application/x-www-form-urlencoded' or 'application/json':
应该是:
elif ctype == 'application/x-www-form-urlencoded' or ctype == 'application/json':
或
elif ctype in ('application/x-www-form-urlencoded', 'application/json'):