使用附加的二进制数据文件和 json 格式的元数据创建 HTTP 获取响应
Create HTTP get response with attached binary data file and json formatted metadata
我正在使用 BaseHTTPServer.BaseHTTPRequestHandler
来实现我的服务器。
目前我仅使用二进制数据文件响应获取请求。
self.send_response(200)
self.send_header("Content-Type", 'application/octet-stream')
self.send_header("Content-Disposition", 'attachment; filename="{}"'.format(os.path.basename(FILEPATH)))
fs = os.fstat(f.fileno())
self.send_header("Content-Length", str(fs.st_size))
self.end_headers()
现在要求添加另一个部分,其中包括一些简短的 json 格式的配置数据(即 {'status': 'ok', 'type': 'keepalive'}
),我宁愿将此信息传递到由唯一 http [= 分隔的同一响应中25=] 或通过 http body.
最好的方法是什么?我想知道如何扩展我的代码来支持它。
谢谢
有很多方法可以做到这一点,我认为最好的选择将取决于您的接收方最容易理解的内容。
最字面的解释是使用内容类型 multipart/mixed
https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html 但您可能不得不在接收端编写自己的解析。我不知道这是否完全符合规格,但它传达了这个想法:
from http.server import BaseHTTPRequestHandler
import http.server
import socketserver
import string
import random
import io
PORT = 8000
class ResponsePart:
def __init__(self, content, content_type):
self.content = content.encode('utf-8')
self.content_type = content_type.encode('utf-8')
class Mine(http.server.BaseHTTPRequestHandler):
def get_separator(self, parts):
while True:
boundary = []
for i in range(32):
boundary.append(random.choice(string.digits + string.ascii_letters))
boundary = ''.join(boundary).encode('ascii')
for part in parts:
if boundary in part:
break
else:
return boundary
def do_GET(self):
responses = [
ResponsePart('abc123', 'Content-type: application/octet-stream'),
ResponsePart('{"a":"b"}', 'Content-type: application/json'),
]
boundary = self.get_separator([r.content for r in responses])
self.send_response(200)
self.send_header("Content-Type", 'multipart/mixed; boundary=' + boundary.decode('ascii'))
self.end_headers()
for piece in responses:
self.wfile.write(b'--')
self.wfile.write(boundary)
self.wfile.write(b'\r\n')
self.wfile.write(piece.content_type)
self.wfile.write(b'\r\n')
self.wfile.write(piece.content)
self.wfile.write(b'\r\n')
Handler = Mine
with socketserver.TCPServer(("", PORT), Handler) as httpd:
httpd.serve_forever()
除此之外,我可能会使用 JSON 或其他方法来执行此操作,以便您返回一个一致的内容类型:
from http.server import BaseHTTPRequestHandler
import http.server
import socketserver
import string
import random
import io
import json
PORT = 8000
class Mine(http.server.BaseHTTPRequestHandler):
def do_GET(self):
response = {
'filedata': 'abc123',
'status': {"a":"b"},
}
output_data = json.dumps(response).encode('utf-8')
self.send_response(200)
self.send_header("Content-Type", 'application/octet-stream')
self.send_header("Content-Length", str(len(output_data)))
self.end_headers()
self.wfile.write(output_data)
Handler = Mine
with socketserver.TCPServer(("", PORT), Handler) as httpd:
httpd.serve_forever()
这在接收端处理起来会容易得多,一个 json 解码就完成了。
我正在使用 BaseHTTPServer.BaseHTTPRequestHandler
来实现我的服务器。
目前我仅使用二进制数据文件响应获取请求。
self.send_response(200)
self.send_header("Content-Type", 'application/octet-stream')
self.send_header("Content-Disposition", 'attachment; filename="{}"'.format(os.path.basename(FILEPATH)))
fs = os.fstat(f.fileno())
self.send_header("Content-Length", str(fs.st_size))
self.end_headers()
现在要求添加另一个部分,其中包括一些简短的 json 格式的配置数据(即 {'status': 'ok', 'type': 'keepalive'}
),我宁愿将此信息传递到由唯一 http [= 分隔的同一响应中25=] 或通过 http body.
最好的方法是什么?我想知道如何扩展我的代码来支持它。
谢谢
有很多方法可以做到这一点,我认为最好的选择将取决于您的接收方最容易理解的内容。
最字面的解释是使用内容类型 multipart/mixed
https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html 但您可能不得不在接收端编写自己的解析。我不知道这是否完全符合规格,但它传达了这个想法:
from http.server import BaseHTTPRequestHandler
import http.server
import socketserver
import string
import random
import io
PORT = 8000
class ResponsePart:
def __init__(self, content, content_type):
self.content = content.encode('utf-8')
self.content_type = content_type.encode('utf-8')
class Mine(http.server.BaseHTTPRequestHandler):
def get_separator(self, parts):
while True:
boundary = []
for i in range(32):
boundary.append(random.choice(string.digits + string.ascii_letters))
boundary = ''.join(boundary).encode('ascii')
for part in parts:
if boundary in part:
break
else:
return boundary
def do_GET(self):
responses = [
ResponsePart('abc123', 'Content-type: application/octet-stream'),
ResponsePart('{"a":"b"}', 'Content-type: application/json'),
]
boundary = self.get_separator([r.content for r in responses])
self.send_response(200)
self.send_header("Content-Type", 'multipart/mixed; boundary=' + boundary.decode('ascii'))
self.end_headers()
for piece in responses:
self.wfile.write(b'--')
self.wfile.write(boundary)
self.wfile.write(b'\r\n')
self.wfile.write(piece.content_type)
self.wfile.write(b'\r\n')
self.wfile.write(piece.content)
self.wfile.write(b'\r\n')
Handler = Mine
with socketserver.TCPServer(("", PORT), Handler) as httpd:
httpd.serve_forever()
除此之外,我可能会使用 JSON 或其他方法来执行此操作,以便您返回一个一致的内容类型:
from http.server import BaseHTTPRequestHandler
import http.server
import socketserver
import string
import random
import io
import json
PORT = 8000
class Mine(http.server.BaseHTTPRequestHandler):
def do_GET(self):
response = {
'filedata': 'abc123',
'status': {"a":"b"},
}
output_data = json.dumps(response).encode('utf-8')
self.send_response(200)
self.send_header("Content-Type", 'application/octet-stream')
self.send_header("Content-Length", str(len(output_data)))
self.end_headers()
self.wfile.write(output_data)
Handler = Mine
with socketserver.TCPServer(("", PORT), Handler) as httpd:
httpd.serve_forever()
这在接收端处理起来会容易得多,一个 json 解码就完成了。