/ internal / desktop / file.go
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  }