1月第一讲:WxPython跨平台开发框架之前后端结合实现附件信息的上传及管理
1、功能描述和界面
- 前端(wxPython GUI):
- 提供文件选择、显示文件列表的界面。
- 支持上传、删除和下载附件。
- 展示上传状态和附件信息(如文件名、大小、上传时间)。
- 后端(REST API 服务):
- 提供上传、删除、获取附件信息的接口。
- 使用常见的 Web 框架(如 Flask 或 FastAPI)实现。
首先前端我们需要一个对所有附件进行管理的界面,以便对于附件进行统一的维护处理。
前端发起上传附件的处理,如下界面所示,可以选择多个不同类型的文件。
上传成功后,我们可以打开附件信息记录,如果是图片会显示出来,如果是其他格式,可以通过打开链接方式下载查看。
2、功能的实现处理
如果附件是简单的上传,比较容易处理,我们可以先了解一下简单的做法,然后在深入探讨实际框架中对于附件的处理。
1) FastAPI 端实现文件上传接口
首先,在 FastAPI 中创建一个接收文件的接口:
from fastapi import FastAPI, File, UploadFile app = FastAPI() @app.post("/upload/") async def upload_file(file: UploadFile = File(...)): with open(file.filename, "wb") as f: f.write(await file.read()) return {"filename": file.filename}
在公布对应的API接口后,在 前端的 wxPython 项目中,您可以通过 requests
库 或者 aiohttp 库 与 FastAPI 交互来实现文件上传。以下是简单的实现步骤和示例代码
import wx import requests class FileUploadFrame(wx.Frame): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) panel = wx.Panel(self) self.upload_button = wx.Button(panel, label="上传文件", pos=(20, 20)) self.upload_button.Bind(wx.EVT_BUTTON, self.on_upload) self.status_text = wx.StaticText(panel, label="", pos=(20, 60)) def on_upload(self, event): with wx.FileDialog( self, "选择文件", wildcard="所有文件 (*.*)|*.*", style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST ) as file_dialog: if file_dialog.ShowModal() == wx.ID_CANCEL: return # 用户取消选择 # 获取文件路径 file_path = file_dialog.GetPath() try: self.upload_file(file_path) except Exception as e: wx.LogError(f"文件上传失败: {e}") def upload_file(self, file_path): url = "http://127.0.0.1:8000/upload/" # FastAPI 服务器的上传接口 with open(file_path, "rb") as file: files = {"file": file} response = requests.post(url, files=files) if response.status_code == 200: self.status_text.SetLabel(f"上传成功: {response.json().get('filename')}") else: self.status_text.SetLabel(f"上传失败: {response.status_code}") if __name__ == "__main__": app = wx.App(False) frame = FileUploadFrame(None, title="文件上传", size=(300, 150)) frame.Show() app.MainLoop()
2) 上传多个文件的处理方式
上面是单个文件的上传处理,如果要一次性提交多个文件到 FastAPI 接口,可以使用 FastAPI 的 List[UploadFile]
类型接收多个文件。以下是完整的实现方法。
from fastapi import FastAPI, File, UploadFile from typing import List app = FastAPI() @app.post("/upload/") async def upload_files(files: List[UploadFile] = File(...)): saved_files = [] for file in files: file_path = f"./uploaded/{file.filename}" # 保存到 uploaded 目录 with open(file_path, "wb") as f: f.write(await file.read()) saved_files.append(file.filename) return {"uploaded_files": saved_files}
https://book.qq.com/book-search/%E5%90%8D%E4%BC%98%E9%A6%86%E7%BD%91%E3%80%9023Y4.com%E3%80%91?c31a
https://book.qq.com/book-search/%E6%B5%B7%E8%A7%92%E7%A4%BE%E5%8C%BA%E3%80%9023Y4.com%E3%80%91?c31b
https://book.qq.com/book-search/%E8%89%B3%E6%AF%8D%E7%BD%91%E8%BF%9B%E3%80%9023Y4.com%E3%80%91?c31c
https://book.qq.com/book-search/%E6%9E%9C%E5%86%BB%E4%BC%A0%E5%AA%92%E3%80%9023Y4.com%E3%80%91?c31d
https://book.qq.com/book-search/%E6%9E%9C%E5%86%BB%E4%BC%A0%E5%AA%92%E8%BF%9B23Y4.com%E7%9C%8B?c31e
https://book.qq.com/book-search/%E6%80%A7%E5%B7%B4%E5%85%8B%E8%BF%9B%E3%80%9023Y4.com%E3%80%91?c31f
https://book.qq.com/book-search/%E7%88%B1%E5%A8%81%E5%A5%B6%E7%BD%91%E3%80%9023Y4.com%E3%80%91?c31g
https://book.qq.com/book-search/%E7%A6%81%E6%BC%AB%E5%A4%A9%E5%A0%82%E3%80%9023Y4.com%E3%80%91?c31h
https://book.qq.com/book-search/%E6%92%B8%E6%92%B8%E7%A4%BE%E7%BD%91%E3%80%9023Y4.com%E3%80%91?c31i
https://book.qq.com/book-search/%E6%8A%96%E9%98%B4%E4%B8%8B%E8%BD%BD%E3%80%8A23Y4.com%E3%80%8B?c31i
https://book.qq.com/book-search/%E6%8A%96%E9%98%B4%E7%BD%91%E7%AB%99%E3%80%9023Y4.com%E3%80%91?c31k
https://book.qq.com/book-search/%E4%B9%85%E4%B9%85%E7%83%AD%E7%9C%8B%E3%80%9023Y4.com%E3%80%91?c31l
https://book.qq.com/book-search/%E4%B9%85%E4%B9%85%E7%83%AD%E8%BF%9B%E3%80%9023Y4.com%E3%80%91?c31m
https://book.qq.com/book-search/%E6%92%B8%E6%92%B8%E7%A4%BE%E8%BF%9B%E3%80%9023Y4.com%E3%80%91?c31n
https://book.qq.com/book-search/%E4%B8%8B%E8%BD%BD%E6%8A%96%E9%98%B4%E3%80%9023Y4.com%E3%80%91?c31o
https://book.qq.com/book-search/%E8%89%B3%E6%AF%8D%E5%9C%B0%E5%9D%80%E3%80%9023Y4.com%E3%80%91?c31p
https://book.qq.com/book-search/%E7%9C%8B%E8%89%B3%E6%AF%8D%E8%BF%9B%E3%80%9023Y4.com%E3%80%91?c31q
https://book.qq.com/book-search/%E8%89%B3%E6%AF%8D%E7%9C%8B%E8%BF%99%E3%80%9023Y4.com%E3%80%91?c31r
https://book.qq.com/book-search/%E8%89%B3%E6%AF%8D%E5%9C%B0%E5%9D%80%E8%BF%9B23Y4.com%E7%9C%8B?c31s
https://book.qq.com/book-search/%E8%89%B3%E6%AF%8D%E5%9C%B0%E5%9D%80%E6%9D%A523Y4.com%E7%9C%8B?c31t
而在前端WxPython的处理中,需要对多个文件进行上传处理即可,可以使用 wx.FileDialog
的多选功能,并通过 requests
库批量上传多个文件。
import wx import requests class MultiFileUploadFrame(wx.Frame): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) panel = wx.Panel(self) self.upload_button = wx.Button(panel, label="上传多个文件", pos=(20, 20)) self.upload_button.Bind(wx.EVT_BUTTON, self.on_upload) self.status_text = wx.StaticText(panel, label="", pos=(20, 60), size=(300, -1)) def on_upload(self, event): with wx.FileDialog( self, "选择文件", wildcard="所有文件 (*.*)|*.*", style=wx.FD_OPEN | wx.FD_MULTIPLE ) as file_dialog: if file_dialog.ShowModal() == wx.ID_CANCEL: return # 用户取消选择 # 获取选择的多个文件路径 file_paths = file_dialog.GetPaths() try: self.upload_files(file_paths) except Exception as e: wx.LogError(f"文件上传失败: {e}") def upload_files(self, file_paths): url = "http://127.0.0.1:8000/upload/" # FastAPI 服务器的上传接口 files = [("files", (file_path.split("/")[-1], open(file_path, "rb"))) for file_path in file_paths] response = requests.post(url, files=files) if response.status_code == 200: uploaded_files = response.json().get("uploaded_files", []) self.status_text.SetLabel(f"上传成功: {', '.join(uploaded_files)}") else: self.status_text.SetLabel(f"上传失败: {response.status_code}") if __name__ == "__main__": app = wx.App(False) frame = MultiFileUploadFrame(None, title="多文件上传", size=(400, 200)) frame.Show() app.MainLoop()
不过我们附件的上传,往往还需要伴随着一些额外的信息,方便把这些信息存储在数据库中供查询参考,同时也是关联业务模块和附件信息的重要依据。
如果需要在上传多个文件的同时传递额外参数(如 guid
和 folder
),可以将这些参数通过 POST 请求的表单数据 (data
) 传递。FastAPI 可以同时处理文件和表单数据。