1、功能描述和界面
- 前端(wxPython GUI):
- 提供文件選擇、顯示文件列表的界面。
- 支持上傳、刪除和下載附件。
- 展示上傳狀態和附件信息(如文件名、大小、上傳時間)。
- 后端(REST API 服務):
- 提供上傳、刪除、獲取附件信息的接口。
- 使用常見的 Web 框架(如 Flask 或 FastAPI)實現。
首先前端我們需要一個對所有附件進行管理的界面,以便對于附件進行統一的維護處理。
前端發起上傳附件的處理,如下界面所示,可以選擇多個不同類型的文件。
?上傳成功后,我們可以打開附件信息記錄,如果是圖片會顯示出來,如果是其他格式,可以通過打開鏈接方式下載查看。
2、功能的實現處理
如果附件是簡單的上傳,比較容易處理,我們可以先了解一下簡單的做法,然后在深入探討實際框架中對于附件的處理。
1) FastAPI 端實現文件上傳接口
首先,在 FastAPI 中創建一個接收文件的接口:
from fastapi import FastAPI, File, UploadFileapp = 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 requestsclass 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 Listapp = 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 requestsclass 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 可以同時處理文件和表單數據。?