You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WxPython应用中接收从Outlook拖拽的附件并获取文件内容

解决方案

问题根因

  • wxPython 的 wx.DataObjectComposite 默认仅自动拉取优先级最高的单种格式数据,不会主动获取所有注册格式的内容
  • FileContents 属于延迟请求格式,Outlook 不会主动发送该格式数据,需要你在拿到 FileGroupDescriptorW 的文件名列表后,按附件索引主动请求对应内容
  • 当前代码使用 ANSI 版结构体规则解析 Unicode 格式的文件名,会出现乱码问题

完整可运行实现代码

import struct
import wx

class MainFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)
        self.drop_target = MyDropTarget()
        self.SetSize((800, 600))
        self.SetDropTarget(self.drop_target)
        self.Center()

class MyDropTarget(wx.DropTarget):
    def __init__(self):
        wx.DropTarget.__init__(self)
        # 注册三种拖拽格式
        self.file_contents_format = wx.DataFormat("FileContents")
        self.file_group_format = wx.DataFormat("FileGroupDescriptor")
        self.file_group_w_format = wx.DataFormat("FileGroupDescriptorW")
        
        self.composite = wx.DataObjectComposite()
        self.file_contents_obj = wx.CustomDataObject(self.file_contents_format)
        self.file_group_obj = wx.CustomDataObject(self.file_group_format)
        self.file_group_w_obj = wx.CustomDataObject(self.file_group_w_format)
        
        # 优先取Unicode版的文件描述符
        self.composite.Add(self.file_group_w_obj, preferred=True)
        self.composite.Add(self.file_group_obj)
        self.composite.Add(self.file_contents_obj)
        
        self.SetDataObject(self.composite)

    def OnDrop(self, x, y):
        return True

    def OnData(self, x, y, result):
        if not self.GetData():
            return result
        
        recv_format = self.composite.GetReceivedFormat()
        # 先解析文件描述符获取文件名列表
        filenames = []
        if recv_format == self.file_group_w_format:
            # Unicode版结构体解析规则 小端序
            data = self.file_group_w_obj.GetData()
            file_count = struct.unpack("<i", data[:4])[0]
            # FILEDESCRIPTORW 结构最后字段为520字节的宽字符文件名数组
            fmt = "<i16s8s8si8s8s8sii520s"
            for item in struct.iter_unpack(fmt, data[4:]):
                # 解码宽字符文件名
                filename = item[10].decode("utf-16-le").rstrip("\x00")
                filenames.append(filename)
        elif recv_format == self.file_group_format:
            # ANSI版结构体解析规则
            data = self.file_group_obj.GetData()
            file_count = struct.unpack("<i", data[:4])[0]
            fmt = "<i16s8s8si8s8s8sii260s"
            for item in struct.iter_unpack(fmt, data[4:]):
                filename = item[10].decode("gbk").rstrip("\x00")
                filenames.append(filename)
        
        # 主动拉取每个附件的内容
        for idx, filename in enumerate(filenames):
            # 指定要请求的附件索引
            self.file_contents_obj.SetIndex(idx)
            # 主动请求当前索引对应的FileContents数据
            if self.GetData(self.file_contents_format):
                file_content = self.file_contents_obj.GetData()
                # 保存到当前运行目录
                with open(filename, "wb") as f:
                    f.write(file_content)
                print(f"已成功保存附件:{filename}")
        
        return result

if __name__ == "__main__":
    app = wx.App(redirect=False)
    frame = MainFrame(None, title="Outlook附件拖拽接收")
    frame.Show()
    app.MainLoop()

使用说明

  • 运行程序后直接从Outlook邮件中拖拽附件到窗口区域即可自动保存到程序运行目录
  • 支持单个、多个附件同时拖拽,兼容中文文件名

内容的提问来源于stack exchange,提问作者Anton Lahti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 06:54:03