文件同步
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

handle.go 18 KiB

4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
4 yıl önce
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. package handle
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "fts/config"
  6. "fts/etcdclient"
  7. "github.com/gorilla/websocket"
  8. _ "github.com/ipfs/go-ipfs-api"
  9. shell "github.com/ipfs/go-ipfs-api"
  10. "io"
  11. "log"
  12. "os"
  13. "os/exec"
  14. "path"
  15. "path/filepath"
  16. "strconv"
  17. "strings"
  18. "time"
  19. )
  20. var gobalLoginUserName string
  21. //key:filepath,value:hash
  22. var gobalFileMap = make(map[string] string)
  23. var gobalFileUpdateTimeMap = make(map[string] string)
  24. //var gobalFileChangeMap = make(map[string] string)
  25. var getLocalFileListDir string
  26. var gobalSubscriptionFileChangeSwitch int =0 //订阅文件变更开关
  27. var ipfsPath=os.Getenv("IPFS-PATH")
  28. /**
  29. 文件上传下载进度
  30. */
  31. type processStruct struct {
  32. Size string `json:"size"`
  33. CurrentSize string `json:"currentSize"`
  34. Unit string `json:"unit"`
  35. CurrentUnit string `json:"currentUnit"`
  36. Process float64 `json:"process"`
  37. Hash string `json:"hash"`
  38. }
  39. func main() {
  40. //config.InitConfig()
  41. //InitLocalWorkSpace("320872793405132801","test1")
  42. //
  43. //DownCommand("QmTp2hEo8eXRp6wg7jXv1BLCMh5a4F3B7buAUZNZUu772j","testOne","hello.txt","a/b/")
  44. //
  45. //UploadCommand("C:\\Users\\yuan_rh\\Downloads\\QmRzN7uW6HCVAkGMXNWv3rC9dqPJijvEgvtW6DKsQQE8Js","QmRzN7uW6HCVAkGMXNWv3rC9dqPJijvEgvtW6DKsQQE8Js","testOne","a/b/")
  46. //
  47. //GetLocalFileList("testOne")
  48. }
  49. /**
  50. 初始化本地工作目录
  51. @param userId 用户ID
  52. @param projectName 项目名称
  53. */
  54. func InitLocalWorkSpace(conn *websocket.Conn,userName,projectName string) (error){
  55. //空格路径处理
  56. ipfsPath=strings.Replace(os.Getenv("IPFS-PATH"),"\"","",1)+"\\ipfs.exe"
  57. //初始化当前登陆用户
  58. gobalLoginUserName = userName
  59. // 检查本地目录是否存在
  60. var projectPath = config.LocalWorkSpaceDir+userName+"\\"+projectName
  61. _,err := os.Stat(projectPath)
  62. if err != nil {
  63. //创建文件目录
  64. os.MkdirAll(projectPath, os.ModePerm)
  65. }
  66. log.Println("切换本地工作目录至 "+projectPath)
  67. if err := conn.WriteMessage(websocket.TextMessage, []byte(fmt.Sprint(projectPath))); err != nil {
  68. log.Println(err)
  69. return err
  70. }
  71. return nil
  72. }
  73. /**
  74. 初始化本地客户端配置
  75. */
  76. func InitClientConfig(ipfsApi,ipfsBootstrap string) error{
  77. //空格路径处理
  78. ipfsPath=strings.Replace(os.Getenv("IPFS-PATH"),"\"","",1)+"\\ipfs.exe"
  79. config.ServerIpfsUrl = ipfsApi
  80. log.Println("初始化客户端配置项IPFS—API:"+config.ServerIpfsUrl)
  81. ipfsBootstraps := strings.Split(ipfsBootstrap,";")
  82. for _, simpleBootstrap := range ipfsBootstraps {
  83. log.Println("增加引导节点:"+simpleBootstrap)
  84. cmd := exec.Command(ipfsPath,"bootstrap", "add", simpleBootstrap)
  85. err :=cmd.Run()
  86. if err!=nil{
  87. return err
  88. }
  89. }
  90. return nil
  91. }
  92. /**
  93. 下载指令
  94. @param hash ipfs哈希值
  95. @param projectName 项目名称
  96. @para fileName 文件名称
  97. @param dir 云文件目录
  98. */
  99. func DownCommand(conn *websocket.Conn, hash, projectName, fileName, dir string) error{
  100. absoluteDir := config.LocalWorkSpaceDir+gobalLoginUserName+"\\"+projectName+"\\"+dir
  101. //检查目录
  102. _,err := os.Stat(absoluteDir)
  103. if err != nil {
  104. //创建文件目录
  105. err = os.MkdirAll(absoluteDir, os.ModePerm)
  106. if err!=nil{
  107. log.Println(err)
  108. return err
  109. }
  110. }
  111. var downloading bool = false
  112. //检测文件打开状态
  113. tfile,err := os.OpenFile(fmt.Sprint(absoluteDir+"\\"+fileName),os.O_RDWR,1)
  114. if err != nil && (!os.IsNotExist(err)) {
  115. log.Println("文件被占用,请关闭打开的软件")
  116. if err := conn.WriteMessage(websocket.TextMessage, []byte("-2")); err != nil {
  117. return err
  118. }
  119. return err
  120. }
  121. defer tfile.Close()
  122. //serverSh := shell.NewShell(config.ServerIpfsUrl)
  123. ////检测引导节点是否连接成功
  124. //isUp := serverSh.IsUp()
  125. //if !isUp {
  126. // if err := conn.WriteMessage(websocket.TextMessage, []byte("-1")); err != nil {
  127. // return err
  128. // }
  129. // return nil
  130. //}
  131. cmd := exec.Command(ipfsPath,"get", hash,"-o",fmt.Sprint(absoluteDir+"\\"+fileName))
  132. progress := make(chan string,10000)
  133. var stdout, stderr []byte
  134. var errStdout, errStderr error
  135. stdoutIn, _ := cmd.StdoutPipe()
  136. stderrIn, _ := cmd.StderrPipe()
  137. cmd.Start()
  138. go func() {
  139. stdout, errStdout = copyAndCapture(os.Stdout, stdoutIn, progress)
  140. }()
  141. go func() {
  142. stderr, errStderr = copyAndCapture(os.Stderr, stderrIn, progress)
  143. }()
  144. go func(){
  145. millSeconds := time.Now().UnixNano() / 1e6
  146. for content := range progress { // 通道关闭后会退出for range循环
  147. current :=time.Now().UnixNano() / 1e6
  148. if current-millSeconds>500{
  149. projson,err := contentToJSONByte(content)
  150. if projson==nil && err==nil{
  151. continue
  152. }
  153. if err != nil {
  154. log.Printf("json.Marshal error %s\n", err)
  155. }
  156. millSeconds = current
  157. downloading = true
  158. if err := conn.WriteMessage(websocket.TextMessage, projson); err != nil {
  159. log.Println(err)
  160. break
  161. }
  162. }
  163. if strings.Index(content,"100.00%")!=-1{
  164. projson,err := contentToJSONByte(content)
  165. if projson==nil && err==nil{
  166. continue
  167. }
  168. if err != nil {
  169. log.Printf("json.Marshal error %s\n", err)
  170. }
  171. downloading = true
  172. if err := conn.WriteMessage(websocket.TextMessage, projson); err != nil {
  173. panic(err)
  174. }
  175. break
  176. }
  177. }
  178. }()
  179. log.Println("下载资源连接中...")
  180. //设置30秒连接超时
  181. go func() {
  182. index :=0
  183. for true{
  184. index++
  185. if downloading==true{
  186. return
  187. }
  188. time.Sleep(time.Duration(1)*time.Second)
  189. if downloading==false && index==30{
  190. err = cmd.Process.Kill()
  191. log.Println("进程连接超时30s已被Kill")
  192. if err := conn.WriteMessage(websocket.TextMessage, []byte("-1")); err != nil {
  193. return
  194. }
  195. return
  196. }
  197. }
  198. }()
  199. err = cmd.Wait()
  200. if err != nil {
  201. log.Printf("cmd.Run() failed with %s\n", err)
  202. }
  203. if errStdout != nil || errStderr != nil {
  204. log.Printf("failed to capture stdout or stderr\n")
  205. }
  206. outStr := string(stdout)
  207. log.Printf("out:%s", outStr)
  208. //TODO test 更新数据库hash
  209. key := gobalLoginUserName+"\\"+projectName+"\\"+dir+"\\"+fileName
  210. err = etcdclient.ReplaceInto(key,hash)
  211. if err != nil {
  212. log.Println(err)
  213. return err
  214. }
  215. if err==nil{
  216. log.Println("下载成功")
  217. }
  218. //time.Sleep(time.Duration(6)*time.Second)
  219. defer close(progress)
  220. return nil
  221. }
  222. func contentToJSONByte(content string) ([]byte,error){
  223. sts :=strings.Split(content," ")
  224. if len(sts)<8{
  225. log.Println("字符长度小于8")
  226. return nil,nil
  227. }
  228. var processFloat float64
  229. if (len(sts)==9 || len(sts)==8){
  230. processFloat,_ =strconv.ParseFloat(strings.Replace(sts[7],"%","",1), 64)
  231. }else{
  232. processFloat,_ =strconv.ParseFloat(strings.Replace(sts[8],"%","",1), 64)
  233. }
  234. if processFloat==0{
  235. //log.Println("当前进度0")
  236. return nil,nil
  237. }
  238. pro :=&processStruct{
  239. Size:sts[4],
  240. CurrentSize: sts[1],
  241. Unit: sts[2],
  242. CurrentUnit: sts[5],
  243. Process: processFloat,
  244. Hash: "",
  245. }
  246. projson,err :=json.Marshal(pro)
  247. return projson,err
  248. }
  249. /**
  250. 上传本地文件
  251. @param absolutePath 文件本地绝对路径
  252. @param fileName 文件名称
  253. @param projectName 项目名称
  254. @param dir 云文件目录
  255. */
  256. func UploadCommand(conn *websocket.Conn,absolutePath,fileName,projectName,dir string) error{
  257. //本地拷贝文件
  258. absoluteDir := config.LocalWorkSpaceDir+gobalLoginUserName+"\\"+projectName+"\\"+dir
  259. //检查目录
  260. _,err := os.Stat(absoluteDir)
  261. if err != nil {
  262. //创建文件目录
  263. err = os.MkdirAll(absoluteDir, os.ModePerm)
  264. if err!=nil{
  265. return err
  266. }
  267. }
  268. //检测文件打开状态
  269. tfile,err := os.OpenFile(absolutePath,os.O_RDWR,1)
  270. if err != nil {
  271. log.Println("文件被占用,请关闭打开的软件")
  272. if err := conn.WriteMessage(websocket.TextMessage, []byte("-2")); err != nil {
  273. return err
  274. }
  275. return err
  276. }
  277. defer tfile.Close()
  278. serverSh := shell.NewShell(config.ServerIpfsUrl)
  279. serverSh.SetTimeout(time.Duration(30)*time.Second)
  280. log.Println("检测引导节点存活情况"+config.ServerIpfsUrl)
  281. //检测引导节点是否连接成功
  282. isUp := serverSh.IsUp()
  283. if !isUp {
  284. if err := conn.WriteMessage(websocket.TextMessage, []byte("-1")); err != nil {
  285. return err
  286. }
  287. return nil
  288. }
  289. var uploading bool=false
  290. cmd := exec.Command(ipfsPath, "add",absolutePath)
  291. uploadProgress := make(chan string,10000)
  292. var stdout, stderr []byte
  293. var errStdout, errStderr error
  294. stdoutIn, _ := cmd.StdoutPipe()
  295. stderrIn, _ := cmd.StderrPipe()
  296. cmd.Start()
  297. go func() {
  298. stdout, errStdout = copyAndCapture(os.Stdout, stdoutIn, uploadProgress)
  299. }()
  300. go func() {
  301. stderr, errStderr = copyAndCapture(os.Stderr, stderrIn, uploadProgress)
  302. }()
  303. go func(){
  304. millSeconds := time.Now().UnixNano() / 1e6
  305. for content := range uploadProgress { // 通道关闭后会退出for range循环
  306. current :=time.Now().UnixNano() / 1e6
  307. if current-millSeconds>500{
  308. projson,err := contentToJSONByte(content)
  309. if projson==nil && err==nil{
  310. continue
  311. }
  312. if err != nil {
  313. log.Println("json.Marshal error %s\n", err)
  314. }
  315. uploading=true
  316. if err := conn.WriteMessage(websocket.TextMessage, projson); err != nil {
  317. break
  318. }
  319. millSeconds = current
  320. }
  321. if strings.Index(content,"100.00%")!=-1{
  322. projson,err := contentToJSONByte(content)
  323. if projson==nil && err==nil{
  324. continue
  325. }
  326. if err != nil {
  327. log.Println("json.Marshal error %s\n", err)
  328. }
  329. uploading=true
  330. if err := conn.WriteMessage(websocket.TextMessage, projson); err != nil {
  331. panic(err)
  332. }
  333. break
  334. }
  335. }
  336. }()
  337. log.Println("文件上传中...")
  338. //设置30秒连接超时
  339. go func() {
  340. index :=0
  341. for true{
  342. index++
  343. if uploading==true{
  344. return
  345. }
  346. time.Sleep(time.Duration(1)*time.Second)
  347. if uploading==false && index==30{
  348. err = cmd.Process.Kill()
  349. log.Println("进程连接超时30s已被Kill")
  350. if err := conn.WriteMessage(websocket.TextMessage, []byte("-1")); err != nil {
  351. return
  352. }
  353. return
  354. }
  355. }
  356. }()
  357. err = cmd.Wait()
  358. if err != nil {
  359. log.Println("cmd.Run() failed with %s\n", err)
  360. }
  361. if errStdout != nil || errStderr != nil {
  362. log.Println("failed to capture stdout or stderr\n")
  363. }
  364. outStr := string(stdout)
  365. log.Printf("out:%s", outStr)
  366. /*sh.Get(hash,absoluteDir+fileName)
  367. if err != nil {
  368. return "",err
  369. }*/
  370. defer close(uploadProgress)
  371. prog := new(processStruct)
  372. prog.Hash=strings.Split(outStr," ")[1]
  373. prog.Process=100.00
  374. sh := shell.NewShell(config.GobalIpfsUrl)
  375. sh.SetTimeout(time.Duration(30)*time.Second)
  376. objectStat,err :=sh.ObjectStat(prog.Hash)
  377. if err != nil {
  378. log.Println(err)
  379. return err
  380. }
  381. prog.Size=strconv.Itoa(objectStat.CumulativeSize)
  382. projson,err :=json.Marshal(prog)
  383. serverSh.SetTimeout(time.Duration(30)*time.Second)
  384. err = serverSh.Pin(prog.Hash)
  385. if err != nil {
  386. log.Println("引导节点备份失败")
  387. log.Println(err)
  388. if err := conn.WriteMessage(websocket.TextMessage, []byte("-1")); err != nil {
  389. return err
  390. }
  391. return err
  392. }
  393. if err := conn.WriteMessage(websocket.TextMessage, projson); err != nil {
  394. log.Println(err)
  395. }
  396. log.Println("引导节点文件备份成功")
  397. //本地文件夹拷贝
  398. err = sh.Get(prog.Hash,fmt.Sprint((absoluteDir+"\\"+fileName)))
  399. if err != nil {
  400. log.Println(err)
  401. return err
  402. }
  403. //TODO test 更新数据库hash
  404. key := gobalLoginUserName+"\\"+projectName+"\\"+dir+"\\"+fileName
  405. err = etcdclient.ReplaceInto(key,prog.Hash)
  406. if err != nil {
  407. log.Println(err)
  408. return err
  409. }
  410. log.Println("上传成功")
  411. return nil
  412. }
  413. func copyAndCapture(w io.Writer, r io.Reader, progress chan string) ([]byte, error) {
  414. var out []byte
  415. buf := make([]byte, 1024, 1024)
  416. for {
  417. n, err := r.Read(buf[:])
  418. if n > 0 {
  419. d := buf[:n]
  420. out = append(out, d...)
  421. progress <- string(d)
  422. }
  423. if err != nil {
  424. // Read returns io.EOF at the end of file, which is not an error for us
  425. if err == io.EOF {
  426. err = nil
  427. }
  428. return out, err
  429. }
  430. }
  431. // never reached
  432. panic(true)
  433. return nil, nil
  434. }
  435. /**
  436. 单个文件信息
  437. */
  438. type simpleFileInfo struct {
  439. Name string `json:"name" `
  440. Extension string `json:"extension"`
  441. RelativePath string `json:"relativePath"`
  442. AbsolutePath string `json:"absolutePath"`
  443. }
  444. var gobalFolderFileMap map[string] *simpleFileInfo
  445. var gobalRelativePath string
  446. /**
  447. 获取指定目录或文件的文件信息,如果是目录递归获取文件信息
  448. @param id 文件id
  449. */
  450. func GetFolderFileInfo(conn *websocket.Conn,absolutePath string) error{
  451. gobalFolderFileMap = make(map[string] *simpleFileInfo)
  452. fileInfo,err :=os.Stat(absolutePath)
  453. if err!=nil{
  454. log.Println(err)
  455. return err
  456. }
  457. log.Println(filepath.Dir(absolutePath))
  458. //单个文件处理
  459. if !fileInfo.IsDir() {
  460. simpleFileInfo := new(simpleFileInfo)
  461. simpleFileInfo.Name=fileInfo.Name()
  462. simpleFileInfo.Extension=path.Ext(absolutePath)
  463. simpleFileInfo.RelativePath=""
  464. simpleFileInfo.AbsolutePath=absolutePath
  465. gobalFolderFileMap[absolutePath]=simpleFileInfo
  466. bytes,err :=json.Marshal(gobalFolderFileMap)
  467. if err != nil {
  468. log.Println(err)
  469. return err
  470. }
  471. if err := conn.WriteMessage(websocket.TextMessage, bytes); err != nil {
  472. log.Println(err)
  473. return err
  474. }
  475. return nil
  476. }
  477. //文件目录处理
  478. gobalRelativePath = filepath.Dir(absolutePath)
  479. err =filepath.Walk(absolutePath, myWalkfunc)
  480. if err != nil {
  481. log.Println(err)
  482. return err
  483. }
  484. bytes,err :=json.Marshal(gobalFolderFileMap)
  485. if err != nil {
  486. log.Println(err)
  487. return err
  488. }
  489. if err := conn.WriteMessage(websocket.TextMessage, bytes); err != nil {
  490. log.Println(err)
  491. return err
  492. }
  493. return nil
  494. }
  495. func myWalkfunc(path string, info os.FileInfo, err error) error {
  496. if info.IsDir()==false{
  497. simpleFileInfo := new(simpleFileInfo)
  498. simpleFileInfo.Name=info.Name()
  499. simpleFileInfo.Extension=filepath.Ext(path)
  500. simpleFileInfo.RelativePath=filepath.Dir(strings.Replace(path,gobalRelativePath,"",1))
  501. simpleFileInfo.AbsolutePath=path
  502. gobalFolderFileMap[path]=simpleFileInfo
  503. return nil
  504. }
  505. return nil
  506. }
  507. /**
  508. 本地文件是否存在
  509. */
  510. func fileExist(path string) bool {
  511. _, err := os.Lstat(path)
  512. return !os.IsNotExist(err)
  513. }
  514. /**
  515. 获取本地文件列表
  516. */
  517. func SubscriptionFileChange(conn *websocket.Conn, projectName string) error{
  518. getLocalFileListDir = fmt.Sprint(config.LocalWorkSpaceDir+gobalLoginUserName+"\\"+projectName+"\\")
  519. keyPrefix := gobalLoginUserName+"\\"+projectName+"\\"
  520. //定期校验缓存的本地文件状态
  521. go func() {
  522. for true {
  523. time.Sleep(time.Duration(1)*time.Minute)
  524. dataMap,err := etcdclient.QueryWithPrefix(keyPrefix)
  525. if err != nil {
  526. log.Println(err)
  527. continue
  528. }
  529. if dataMap!=nil && len(dataMap)>0{
  530. for k,_ := range dataMap {
  531. if !fileExist(config.LocalWorkSpaceDir+k){
  532. err = etcdclient.DeleteWithPrefix(k)
  533. if err != nil {
  534. log.Println(err)
  535. }
  536. }
  537. }
  538. }
  539. }
  540. }()
  541. for true {
  542. //优先etcd查询
  543. dataMap,err := etcdclient.QueryWithPrefix(keyPrefix)
  544. if err != nil {
  545. log.Println(err)
  546. return err
  547. }
  548. if dataMap!=nil && len(dataMap)>0{
  549. cacheMap := make(map[string] string)
  550. for k,v := range dataMap {
  551. cacheMap[strings.Replace(k,gobalLoginUserName+"\\"+projectName+"\\","",1)]=v
  552. }
  553. mapByte,err:=json.Marshal(cacheMap)
  554. if err != nil {
  555. log.Println(err)
  556. return err
  557. }
  558. if err := conn.WriteMessage(websocket.TextMessage, mapByte); err != nil {
  559. log.Println(err)
  560. return err
  561. }
  562. time.Sleep(time.Duration(1)*time.Minute)
  563. continue
  564. }
  565. // 不存在则初始化进etcd
  566. err =filepath.Walk(getLocalFileListDir,walkfunc)
  567. if err != nil {
  568. log.Println(err)
  569. //time.Sleep(time.Duration(1)*time.Minute)
  570. }
  571. mapByte,err:=json.Marshal(gobalFileMap)
  572. if err != nil {
  573. log.Println(err)
  574. return err
  575. }
  576. if err := conn.WriteMessage(websocket.TextMessage, mapByte); err != nil {
  577. log.Println(err)
  578. return err
  579. }
  580. cacheMap := make(map[string] string)
  581. for k,v := range gobalFileMap {
  582. k := strings.Replace(k,config.LocalWorkSpaceDir,"",1)
  583. cacheMap[k]=v
  584. }
  585. //异步缓存
  586. //go func() {
  587. err = etcdclient.BatchAdd(cacheMap)
  588. if err != nil {
  589. log.Println(err)
  590. }
  591. //}()
  592. //log.Println("检查本地目录文件变更状态,执行睡眠时间1分钟")
  593. //清空gobalFileMap
  594. gobalFileMap = make(map[string] string)
  595. time.Sleep(time.Duration(1)*time.Minute)
  596. }
  597. return nil
  598. }
  599. /**
  600. TODO 文件变更通知
  601. */
  602. func FileChangeNotify(){
  603. }
  604. /**
  605. TODO 监视文件变动
  606. */
  607. func WatchFile(filePaths string) error{
  608. if len(filePaths)==0{
  609. //TODO
  610. return nil
  611. }
  612. files := strings.Split(filePaths,";")
  613. for _,file := range files{
  614. err :=config.GobalWatch.Add(file)
  615. if err != nil {
  616. log.Println(err)
  617. }
  618. log.Println("文件[ "+file+" ]添加监听事件成功")
  619. }
  620. return nil
  621. }
  622. /**
  623. 打开方式
  624. */
  625. func OpenFileWith(filePath string) error{
  626. //判断文件有效性
  627. _,err := os.Stat(filePath)
  628. if err!=nil{
  629. return err
  630. }
  631. //filePath = strings.Replace(filePath," ","~1",1)
  632. cmd := exec.Command("rundll32.exe","shell32.dll,OpenAs_RunDLL",filePath);
  633. err =cmd.Run()
  634. if err!=nil{
  635. log.Println(err)
  636. return err
  637. }
  638. return nil
  639. }
  640. /**
  641. 手动检查软件更新
  642. 0:不强制更新
  643. 1:强制更新
  644. */
  645. func CheckForUpdates(forceUpdate string) error{
  646. tszdir :=os.Getenv("TSZDIR")
  647. //空格路径处理
  648. ipfsPath=strings.Replace(os.Getenv("IPFS-PATH"),"\"","",1)+"\\stop.vbs"
  649. //判断文件有效性
  650. _,err := os.Stat(tszdir+config.UpdaterName)
  651. if err!=nil{
  652. return err
  653. }
  654. cmd := exec.Command(tszdir+config.UpdaterName,"/justcheck");
  655. err =cmd.Run()
  656. if err!=nil{
  657. log.Println(err)
  658. return err
  659. }
  660. cmd = exec.Command(tszdir+config.UpdaterName,"/checknow");
  661. err =cmd.Run()
  662. if err!=nil{
  663. log.Println(err)
  664. return err
  665. }
  666. //检测到更新 kill所有客户端进程
  667. log.Println("close all process")
  668. cmd = exec.Command("cmd.exe","/c",ipfsPath);
  669. err =cmd.Run()
  670. if err!=nil{
  671. log.Println(err)
  672. return err
  673. }
  674. return nil
  675. }
  676. func walkfunc(path string, info os.FileInfo, err error) error {
  677. if info.IsDir()==false{
  678. sh := shell.NewShell(config.GobalIpfsUrl)
  679. file,err :=os.Open(path)
  680. if err != nil{
  681. log.Println(err)
  682. return err
  683. }
  684. defer file.Close()
  685. hash,err :=sh.Add(file)
  686. if err != nil {
  687. log.Println(err)
  688. return err
  689. }
  690. dir :=strings.Replace(fmt.Sprint(path),fmt.Sprint(getLocalFileListDir),"",1)
  691. gobalFileMap[dir]=hash
  692. }
  693. return nil
  694. }