基于COT协议,能否通过XML在TCP套接字传输图片与文件?
关于COT协议中通过XML直接在TCP套接字传输文件的问题
当前使用场景
我目前在使用COT协议,当前通过URL方式在XML消息中传输文件,代码示例如下:
import datetime import uuid import xml.etree.ElementTree as ET # 假设以下常量已定义:DATETIME_FORMAT, STALE_DURATION, ATTITUDE, DIMENSION, HOW, CALLSIGN, PACKAGE_FILE_NAME, SERVER_IP, SERVER_PORT, SENDER_CALLSIGN, SENDER_UID, FILESHARE_NAME def composeMessage(uid, lat, lon, file_path=None): # Initialize CoT parameters now = datetime.datetime.utcnow() start = now.strftime(DATETIME_FORMAT) time = now.strftime(DATETIME_FORMAT) stale = (now + datetime.timedelta(minutes=STALE_DURATION)).strftime(DATETIME_FORMAT) if file_path: size = str(calcSize(file_path)) hash = str(calcHash(file_path)) # Build XML event = ET.Element('event') event.set('version', '2.0') event.set('uid', uid) event.set('type', f"a-{ATTITUDE}-{DIMENSION}") event.set('how', HOW) event.set('start', start) event.set('time', time) event.set('stale', stale) detail = ET.SubElement(event, 'detail') contact = ET.SubElement(detail, 'contact') contact.set('callsign', CALLSIGN) remarks = ET.SubElement(detail, 'remarks') if file_path: fileshare = ET.SubElement(detail, 'fileshare') fileshare.set('filename', PACKAGE_FILE_NAME) url = f'http://{SERVER_IP}:{SERVER_PORT}/getfile?file={uid}&sender={SENDER_CALLSIGN}' # how can I turn it into url a file? fileshare.set('senderUrl', url) fileshare.set('sizeInBytes', size) fileshare.set('sha256', hash) fileshare.set('senderUid', SENDER_UID) fileshare.set('senderCallsign', SENDER_CALLSIGN) fileshare.set('name', FILESHARE_NAME) ackreq = ET.SubElement(detail, 'ackrequest') ackreq.set('uid', uuid.uuid4().hex) ackreq.set('ackrequested', 'true') ackreq.set('tag', PACKAGE_FILE_NAME) point = ET.SubElement(event, 'point') point.set('le', '0.0') point.set('ce', '1.0') point.set('hae', '10.0') point.set('lat', str(lat)) point.set('lon', str(lon)) return ET.tostring(event)
问题咨询
我了解到图片和数据可通过XML传输,想咨询是否可以直接通过XML在TCP套接字连接中传输文件?
回答
可以直接通过XML在TCP套接字连接中传输文件,但需要对文件内容做Base64编码处理,具体说明如下:
核心原理
XML是纯文本格式,无法直接存储二进制文件内容。Base64编码能将二进制数据转换为ASCII字符串,使其可以合法嵌入到XML的元素文本或属性中,从而通过TCP套接字传输整个XML消息。
实现步骤
- 编码文件内容:读取文件的二进制数据,用Base64编码为UTF-8字符串
- 嵌入XML结构:在
<fileshare>节点下新增一个子元素(如<content>),将编码后的字符串写入该元素的文本内容 - 接收方解码:解析XML消息时提取
<content>的文本,解码回二进制数据后写入本地文件
修改后的代码示例
import datetime import uuid import xml.etree.ElementTree as ET import base64 # 新增Base64模块引用 # 假设以下常量已定义:DATETIME_FORMAT, STALE_DURATION, ATTITUDE, DIMENSION, HOW, CALLSIGN, PACKAGE_FILE_NAME, SERVER_IP, SERVER_PORT, SENDER_CALLSIGN, SENDER_UID, FILESHARE_NAME def composeMessage(uid, lat, lon, file_path=None): # Initialize CoT parameters now = datetime.datetime.utcnow() start = now.strftime(DATETIME_FORMAT) time = now.strftime(DATETIME_FORMAT) stale = (now + datetime.timedelta(minutes=STALE_DURATION)).strftime(DATETIME_FORMAT) file_content = None if file_path: size = str(calcSize(file_path)) hash = str(calcHash(file_path)) # 读取文件并Base64编码 with open(file_path, 'rb') as f: file_content = base64.b64encode(f.read()).decode('utf-8') # Build XML event = ET.Element('event') event.set('version', '2.0') event.set('uid', uid) event.set('type', f"a-{ATTITUDE}-{DIMENSION}") event.set('how', HOW) event.set('start', start) event.set('time', time) event.set('stale', stale) detail = ET.SubElement(event, 'detail') contact = ET.SubElement(detail, 'contact') contact.set('callsign', CALLSIGN) remarks = ET.SubElement(detail, 'remarks') if file_path: fileshare = ET.SubElement(detail, 'fileshare') fileshare.set('filename', PACKAGE_FILE_NAME) # 移除senderUrl,添加Base64编码的内容节点 content_elem = ET.SubElement(fileshare, 'content') content_elem.text = file_content fileshare.set('sizeInBytes', size) fileshare.set('sha256', hash) fileshare.set('senderUid', SENDER_UID) fileshare.set('senderCallsign', SENDER_CALLSIGN) fileshare.set('name', FILESHARE_NAME) ackreq = ET.SubElement(detail, 'ackrequest') ackreq.set('uid', uuid.uuid4().hex) ackreq.set('ackrequested', 'true') ackreq.set('tag', PACKAGE_FILE_NAME) point = ET.SubElement(event, 'point') point.set('le', '0.0') point.set('ce', '1.0') point.set('hae', '10.0') point.set('lat', str(lat)) point.set('lon', str(lon)) return ET.tostring(event)
注意事项
- 数据体积膨胀:Base64编码会让原始数据体积增加约33%,大文件(如几百MB以上)会导致XML消息过大,可能引发TCP传输延迟、丢包或内存溢出问题,仅推荐用于小文件传输
- 解析兼容性:确保接收方的XML解析器能处理大文本节点,避免因内存不足导致解析失败
- 元数据保留:仍需保留文件名、大小、哈希值等元数据,方便接收方验证文件完整性和正确命名
内容的提问来源于stack exchange,提问作者nogabemist
相关产品推荐
相关产品推荐

