@@ -5,9 +5,11 @@ import (
55 "encoding/json"
66 "fmt"
77 "log"
8+ "mime"
89 "net/http"
910 "os"
1011 "path/filepath"
12+ "strconv"
1113 "strings"
1214 "wechatDataBackup/pkg/utils"
1315 "wechatDataBackup/pkg/wechat"
@@ -21,7 +23,7 @@ const (
2123 configDefaultUserKey = "userConfig.defaultUser"
2224 configUsersKey = "userConfig.users"
2325 configExportPathKey = "exportPath"
24- appVersion = "v1.0.5 "
26+ appVersion = "v1.0.6 "
2527)
2628
2729type FileLoader struct {
@@ -30,6 +32,7 @@ type FileLoader struct {
3032}
3133
3234func NewFileLoader (prefix string ) * FileLoader {
35+ mime .AddExtensionType (".mp3" , "audio/mpeg" )
3336 return & FileLoader {FilePrefix : prefix }
3437}
3538
@@ -39,16 +42,74 @@ func (h *FileLoader) SetFilePrefix(prefix string) {
3942}
4043
4144func (h * FileLoader ) ServeHTTP (res http.ResponseWriter , req * http.Request ) {
42- var err error
4345 requestedFilename := h .FilePrefix + "\\ " + strings .TrimPrefix (req .URL .Path , "/" )
44- // log.Println("Requesting file:", requestedFilename)
45- fileData , err := os .ReadFile (requestedFilename )
46+
47+ file , err := os .Open (requestedFilename )
48+ if err != nil {
49+ http .Error (res , fmt .Sprintf ("Could not load file %s" , requestedFilename ), http .StatusBadRequest )
50+ return
51+ }
52+ defer file .Close ()
53+
54+ fileInfo , err := file .Stat ()
4655 if err != nil {
47- res .WriteHeader (http .StatusBadRequest )
48- res .Write ([]byte (fmt .Sprintf ("Could not load file %s" , requestedFilename )))
56+ http .Error (res , "Could not retrieve file info" , http .StatusInternalServerError )
57+ return
58+ }
59+
60+ fileSize := fileInfo .Size ()
61+ rangeHeader := req .Header .Get ("Range" )
62+ if rangeHeader == "" {
63+ // 无 Range 请求,直接返回整个文件
64+ res .Header ().Set ("Content-Length" , strconv .FormatInt (fileSize , 10 ))
65+ http .ServeContent (res , req , requestedFilename , fileInfo .ModTime (), file )
66+ return
67+ }
68+
69+ var start , end int64
70+ if strings .HasPrefix (rangeHeader , "bytes=" ) {
71+ ranges := strings .Split (strings .TrimPrefix (rangeHeader , "bytes=" ), "-" )
72+ start , _ = strconv .ParseInt (ranges [0 ], 10 , 64 )
73+
74+ if len (ranges ) > 1 && ranges [1 ] != "" {
75+ end , _ = strconv .ParseInt (ranges [1 ], 10 , 64 )
76+ } else {
77+ end = fileSize - 1
78+ }
79+ } else {
80+ http .Error (res , "Invalid Range header" , http .StatusRequestedRangeNotSatisfiable )
81+ return
4982 }
5083
51- res .Write (fileData )
84+ if start < 0 || end >= fileSize || start > end {
85+ http .Error (res , "Requested range not satisfiable" , http .StatusRequestedRangeNotSatisfiable )
86+ return
87+ }
88+
89+ contentType := mime .TypeByExtension (filepath .Ext (requestedFilename ))
90+ if contentType == "" {
91+ contentType = "application/octet-stream"
92+ }
93+ res .Header ().Set ("Content-Type" , contentType )
94+ res .Header ().Set ("Content-Range" , fmt .Sprintf ("bytes %d-%d/%d" , start , end , fileSize ))
95+ res .Header ().Set ("Content-Length" , strconv .FormatInt (end - start + 1 , 10 ))
96+ res .WriteHeader (http .StatusPartialContent )
97+ buffer := make ([]byte , 102400 )
98+ file .Seek (start , 0 )
99+ for current := start ; current <= end ; {
100+ readSize := int64 (len (buffer ))
101+ if end - current + 1 < readSize {
102+ readSize = end - current + 1
103+ }
104+
105+ n , err := file .Read (buffer [:readSize ])
106+ if err != nil {
107+ break
108+ }
109+
110+ res .Write (buffer [:n ])
111+ current += int64 (n )
112+ }
52113}
53114
54115// App struct
@@ -90,7 +151,7 @@ type ErrorMessage struct {
90151// NewApp creates a new App application struct
91152func NewApp () * App {
92153 a := & App {}
93-
154+ log . Println ( "App version:" , appVersion )
94155 a .firstInit = true
95156 a .FLoader = NewFileLoader (".\\ " )
96157 viper .SetConfigName (defaultConfig )
@@ -306,7 +367,7 @@ func (a *App) GetWechatContactList(pageIndex int, pageSize int) string {
306367}
307368
308369func (a * App ) GetWechatMessageListByTime (userName string , time int64 , pageSize int , direction string ) string {
309- log .Println ("GetWechatMessageList :" , userName , pageSize , time , direction )
370+ log .Println ("GetWechatMessageListByTime :" , userName , pageSize , time , direction )
310371 if len (userName ) == 0 {
311372 return "{\" Total\" :0, \" Rows\" :[]}"
312373 }
@@ -318,11 +379,33 @@ func (a *App) GetWechatMessageListByTime(userName string, time int64, pageSize i
318379 }
319380 list , err := a .provider .WeChatGetMessageListByTime (userName , time , pageSize , dire )
320381 if err != nil {
321- log .Println ("WeChatGetMessageList failed:" , err )
382+ log .Println ("GetWechatMessageListByTime failed:" , err )
322383 return ""
323384 }
324385 listStr , _ := json .Marshal (list )
325- log .Println ("GetWechatMessageList:" , list .Total )
386+ log .Println ("GetWechatMessageListByTime:" , list .Total )
387+
388+ return string (listStr )
389+ }
390+
391+ func (a * App ) GetWechatMessageListByType (userName string , time int64 , pageSize int , msgType string , direction string ) string {
392+ log .Println ("GetWechatMessageListByType:" , userName , pageSize , time , msgType , direction )
393+ if len (userName ) == 0 {
394+ return "{\" Total\" :0, \" Rows\" :[]}"
395+ }
396+ dire := wechat .Message_Search_Forward
397+ if direction == "backward" {
398+ dire = wechat .Message_Search_Backward
399+ } else if direction == "both" {
400+ dire = wechat .Message_Search_Both
401+ }
402+ list , err := a .provider .WeChatGetMessageListByType (userName , time , pageSize , msgType , dire )
403+ if err != nil {
404+ log .Println ("WeChatGetMessageListByType failed:" , err )
405+ return ""
406+ }
407+ listStr , _ := json .Marshal (list )
408+ log .Println ("WeChatGetMessageListByType:" , list .Total )
326409
327410 return string (listStr )
328411}
@@ -594,3 +677,39 @@ func (a *App) scanAccountByPath(path string) error {
594677func (a * App ) OepnLogFileExplorer () {
595678 utils .OpenFileOrExplorer (".\\ app.log" , true )
596679}
680+
681+ func (a * App ) SaveFileDialog (file string , alisa string ) string {
682+ filePath := a .FLoader .FilePrefix + file
683+ if _ , err := os .Stat (filePath ); err != nil {
684+ log .Println ("SaveFileDialog:" , err )
685+ return err .Error ()
686+ }
687+
688+ savePath , err := runtime .SaveFileDialog (a .ctx , runtime.SaveDialogOptions {
689+ DefaultFilename : alisa ,
690+ Title : "选择保存路径" ,
691+ })
692+ if err != nil {
693+ log .Println ("SaveFileDialog:" , err )
694+ return err .Error ()
695+ }
696+
697+ if savePath == "" {
698+ return ""
699+ }
700+
701+ dirPath := filepath .Dir (savePath )
702+ if ! utils .PathIsCanWriteFile (dirPath ) {
703+ errStr := "Path Is Can't Write File: " + filepath .Dir (savePath )
704+ log .Println (errStr )
705+ return errStr
706+ }
707+
708+ _ , err = utils .CopyFile (filePath , savePath )
709+ if err != nil {
710+ log .Println ("Error CopyFile" , filePath , savePath , err )
711+ return err .Error ()
712+ }
713+
714+ return ""
715+ }
0 commit comments