file.go
1 package desktop 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 "mime/multipart" 9 "net/http" 10 "os" 11 "path/filepath" 12 13 "fyne.io/fyne/v2" 14 "fyne.io/fyne/v2/dialog" 15 "fyne.io/fyne/v2/storage" 16 ) 17 18 type FileManager struct { 19 window fyne.Window 20 files []string 21 selectedFiles []string // 多文件选择 22 } 23 24 func NewFileManager(window fyne.Window) *FileManager { 25 return &FileManager{ 26 window: window, 27 files: make([]string, 0), 28 selectedFiles: make([]string, 0), 29 } 30 } 31 32 func (fm *FileManager) ShowUploadDialog() { 33 fd := dialog.NewFileOpen(func(reader fyne.URIReadCloser, err error) { 34 if err != nil { 35 dialog.ShowError(err, fm.window) 36 return 37 } 38 if reader == nil { 39 return 40 } 41 42 // 获取文件路径 43 filePath := reader.URI().Path() 44 fileName := filepath.Base(filePath) 45 46 err = fm.uploadFile(filePath, fileName) 47 if err != nil { 48 dialog.ShowError(err, fm.window) 49 return 50 } 51 52 dialog.ShowInformation("成功", "文件上传成功", fm.window) 53 }, fm.window) 54 55 fd.Show() 56 } 57 58 func (fm *FileManager) ShowMultiUploadDialog() { 59 // 清空已选择的文件 60 fm.selectedFiles = make([]string, 0) 61 62 fm.showAddFileDialog() 63 } 64 65 func (fm *FileManager) showAddFileDialog() { 66 fd := dialog.NewFileOpen(func(reader fyne.URIReadCloser, err error) { 67 if err != nil { 68 dialog.ShowError(err, fm.window) 69 return 70 } 71 if reader == nil { 72 return 73 } 74 75 // 获取文件路径 76 filePath := reader.URI().Path() 77 fm.selectedFiles = append(fm.selectedFiles, filePath) 78 reader.Close() 79 80 // 是否继续添加文件 81 continueDialog := dialog.NewConfirm( 82 "添加更多文件", 83 fmt.Sprintf("已选择 %d 个文件。是否继续添加?", len(fm.selectedFiles)), 84 func(cont bool) { 85 if cont { 86 // 继续添加文件 87 fm.showAddFileDialog() 88 } else { 89 // 上传 90 if len(fm.selectedFiles) > 0 { 91 // 文件名列表 92 fileNames := make([]string, len(fm.selectedFiles)) 93 for i, path := range fm.selectedFiles { 94 fileNames[i] = filepath.Base(path) 95 } 96 97 // 上传 98 err := fm.uploadMultipleFiles(fm.selectedFiles, fileNames) 99 if err != nil { 100 dialog.ShowError(err, fm.window) 101 return 102 } 103 104 dialog.ShowInformation("成功", fmt.Sprintf("已上传 %d 个文件", len(fm.selectedFiles)), fm.window) 105 } 106 } 107 }, 108 fm.window, 109 ) 110 continueDialog.Show() 111 }, fm.window) 112 113 fd.SetFilter(storage.NewExtensionFileFilter([]string{".mp4", ".mov", ".avi", ".mkv", ".wmv"})) 114 fd.Show() 115 } 116 117 func (fm *FileManager) uploadFile(filePath, fileName string) error { 118 file, err := os.Open(filePath) 119 if err != nil { 120 return err 121 } 122 defer file.Close() 123 124 // 创建multipart form 125 body := &bytes.Buffer{} 126 writer := multipart.NewWriter(body) 127 part, err := writer.CreateFormFile("file", fileName) 128 if err != nil { 129 return err 130 } 131 _, err = io.Copy(part, file) 132 if err != nil { 133 return err 134 } 135 writer.Close() 136 137 // 发送请求 138 resp, err := http.Post("http://localhost:8888/api/file", writer.FormDataContentType(), body) 139 if err != nil { 140 return err 141 } 142 defer resp.Body.Close() 143 144 var result struct { 145 Error int `json:"error"` 146 Msg string `json:"msg"` 147 Data struct { 148 FilePath string `json:"file_path"` 149 } `json:"data"` 150 } 151 152 err = json.NewDecoder(resp.Body).Decode(&result) 153 if err != nil { 154 return err 155 } 156 157 if result.Error != 0 && result.Error != 200 { 158 return fmt.Errorf(result.Msg) 159 } 160 161 fm.files = append(fm.files, result.Data.FilePath) 162 return nil 163 } 164 165 func (fm *FileManager) uploadMultipleFiles(filePaths []string, fileNames []string) error { 166 // 显示上传进度对话框 167 progress := dialog.NewProgress("上传中", "正在上传文件...", fm.window) 168 progress.Show() 169 defer progress.Hide() 170 171 body := &bytes.Buffer{} 172 writer := multipart.NewWriter(body) 173 174 for i, filePath := range filePaths { 175 file, err := os.Open(filePath) 176 if err != nil { 177 return err 178 } 179 180 part, err := writer.CreateFormFile("file", fileNames[i]) 181 if err != nil { 182 file.Close() 183 return err 184 } 185 186 _, err = io.Copy(part, file) 187 file.Close() 188 if err != nil { 189 return err 190 } 191 192 progress.SetValue(float64(i+1) / float64(len(filePaths))) 193 } 194 writer.Close() 195 196 resp, err := http.Post("http://localhost:8888/api/file", writer.FormDataContentType(), body) 197 if err != nil { 198 return err 199 } 200 defer resp.Body.Close() 201 202 var result struct { 203 Error int `json:"error"` 204 Msg string `json:"msg"` 205 Data struct { 206 FilePath []string `json:"file_path"` 207 } `json:"data"` 208 } 209 210 err = json.NewDecoder(resp.Body).Decode(&result) 211 if err != nil { 212 return err 213 } 214 215 if result.Error != 0 && result.Error != 200 { 216 return fmt.Errorf(result.Msg) 217 } 218 219 fm.files = append(fm.files, result.Data.FilePath...) 220 return nil 221 } 222 223 func (fm *FileManager) GetFileCount() int { 224 return len(fm.files) 225 } 226 227 func (fm *FileManager) GetFileName(index int) string { 228 if index < 0 || index >= len(fm.files) { 229 return "" 230 } 231 return filepath.Base(fm.files[index]) 232 } 233 234 func (fm *FileManager) DownloadFile(index int) { 235 if index < 0 || index >= len(fm.files) { 236 return 237 } 238 239 filePath := fm.files[index] 240 241 dialog.ShowFileSave(func(writer fyne.URIWriteCloser, err error) { 242 if err != nil { 243 dialog.ShowError(err, fm.window) 244 return 245 } 246 if writer == nil { 247 return 248 } 249 250 resp, err := http.Get("http://localhost:8888" + filePath) 251 if err != nil { 252 dialog.ShowError(err, fm.window) 253 return 254 } 255 defer resp.Body.Close() 256 257 _, err = io.Copy(writer, resp.Body) 258 if err != nil { 259 dialog.ShowError(err, fm.window) 260 return 261 } 262 263 writer.Close() 264 dialog.ShowInformation("成功", "文件下载完成", fm.window) 265 }, fm.window) 266 }