文件同步
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  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. if err := conn.WriteMessage(websocket.TextMessage, []byte("-1")); err != nil {
  361. return err
  362. }
  363. return err
  364. }
  365. if errStdout != nil || errStderr != nil {
  366. log.Println("failed to capture stdout or stderr\n")
  367. }
  368. outStr := string(stdout)
  369. log.Printf("out:%s", outStr)
  370. /*sh.Get(hash,absoluteDir+fileName)
  371. if err != nil {
  372. return "",err
  373. }*/
  374. defer close(uploadProgress)
  375. prog := new(processStruct)
  376. prog.Hash=strings.Split(outStr," ")[1]
  377. prog.Process=100.00
  378. sh := shell.NewShell(config.GobalIpfsUrl)
  379. //sh.SetTimeout(time.Duration(30)*time.Second)
  380. objectStat,err :=sh.ObjectStat(prog.Hash)
  381. if err != nil {
  382. log.Println(err)
  383. return err
  384. }
  385. prog.Size=strconv.Itoa(objectStat.CumulativeSize)
  386. projson,err :=json.Marshal(prog)
  387. //
  388. cmd = exec.Command(ipfsPath,"dht","provide",prog.Hash)
  389. err = cmd.Run()
  390. if err != nil {
  391. log.Println(err)
  392. if err := conn.WriteMessage(websocket.TextMessage, []byte("-1")); err != nil {
  393. return err
  394. }
  395. return err
  396. }
  397. //serverSh.SetTimeout(time.Duration(600)*time.Second)
  398. err = serverSh.Pin(prog.Hash)
  399. if err != nil {
  400. log.Println("引导节点备份失败")
  401. log.Println(err)
  402. if err := conn.WriteMessage(websocket.TextMessage, []byte("-1")); err != nil {
  403. return err
  404. }
  405. return err
  406. }
  407. log.Println("引导节点文件备份成功")
  408. //本地文件夹拷贝
  409. err = sh.Get(prog.Hash,fmt.Sprint((absoluteDir+"\\"+fileName)))
  410. if err != nil {
  411. log.Println(err)
  412. return err
  413. }
  414. //TODO test 更新数据库hash
  415. key := gobalLoginUserName+"\\"+projectName+"\\"+dir+"\\"+fileName
  416. err = etcdclient.ReplaceInto(key,prog.Hash)
  417. if err != nil {
  418. log.Println(err)
  419. return err
  420. }
  421. if err := conn.WriteMessage(websocket.TextMessage, projson); err != nil {
  422. log.Println(err)
  423. }
  424. log.Println("上传成功")
  425. return nil
  426. }
  427. func copyAndCapture(w io.Writer, r io.Reader, progress chan string) ([]byte, error) {
  428. var out []byte
  429. buf := make([]byte, 1024, 1024)
  430. for {
  431. n, err := r.Read(buf[:])
  432. if n > 0 {
  433. d := buf[:n]
  434. out = append(out, d...)
  435. progress <- string(d)
  436. }
  437. if err != nil {
  438. // Read returns io.EOF at the end of file, which is not an error for us
  439. if err == io.EOF {
  440. err = nil
  441. }
  442. return out, err
  443. }
  444. }
  445. // never reached
  446. panic(true)
  447. return nil, nil
  448. }
  449. /**
  450. 单个文件信息
  451. */
  452. type simpleFileInfo struct {
  453. Name string `json:"name" `
  454. Extension string `json:"extension"`
  455. RelativePath string `json:"relativePath"`
  456. AbsolutePath string `json:"absolutePath"`
  457. }
  458. var gobalFolderFileMap map[string] *simpleFileInfo
  459. var gobalRelativePath string
  460. /**
  461. 获取指定目录或文件的文件信息,如果是目录递归获取文件信息
  462. @param id 文件id
  463. */
  464. func GetFolderFileInfo(conn *websocket.Conn,absolutePath string) error{
  465. gobalFolderFileMap = make(map[string] *simpleFileInfo)
  466. fileInfo,err :=os.Stat(absolutePath)
  467. if err!=nil{
  468. log.Println(err)
  469. return err
  470. }
  471. log.Println(filepath.Dir(absolutePath))
  472. //单个文件处理
  473. if !fileInfo.IsDir() {
  474. simpleFileInfo := new(simpleFileInfo)
  475. simpleFileInfo.Name=fileInfo.Name()
  476. simpleFileInfo.Extension=path.Ext(absolutePath)
  477. simpleFileInfo.RelativePath=""
  478. simpleFileInfo.AbsolutePath=absolutePath
  479. gobalFolderFileMap[absolutePath]=simpleFileInfo
  480. bytes,err :=json.Marshal(gobalFolderFileMap)
  481. if err != nil {
  482. log.Println(err)
  483. return err
  484. }
  485. if err := conn.WriteMessage(websocket.TextMessage, bytes); err != nil {
  486. log.Println(err)
  487. return err
  488. }
  489. return nil
  490. }
  491. //文件目录处理
  492. gobalRelativePath = filepath.Dir(absolutePath)
  493. err =filepath.Walk(absolutePath, myWalkfunc)
  494. if err != nil {
  495. log.Println(err)
  496. return err
  497. }
  498. bytes,err :=json.Marshal(gobalFolderFileMap)
  499. if err != nil {
  500. log.Println(err)
  501. return err
  502. }
  503. if err := conn.WriteMessage(websocket.TextMessage, bytes); err != nil {
  504. log.Println(err)
  505. return err
  506. }
  507. return nil
  508. }
  509. func myWalkfunc(path string, info os.FileInfo, err error) error {
  510. if info.IsDir()==false{
  511. simpleFileInfo := new(simpleFileInfo)
  512. simpleFileInfo.Name=info.Name()
  513. simpleFileInfo.Extension=filepath.Ext(path)
  514. simpleFileInfo.RelativePath=filepath.Dir(strings.Replace(path,gobalRelativePath,"",1))
  515. simpleFileInfo.AbsolutePath=path
  516. gobalFolderFileMap[path]=simpleFileInfo
  517. return nil
  518. }
  519. return nil
  520. }
  521. /**
  522. 本地文件是否存在
  523. */
  524. func fileExist(path string) bool {
  525. _, err := os.Lstat(path)
  526. return !os.IsNotExist(err)
  527. }
  528. /**
  529. 获取本地文件列表
  530. */
  531. func SubscriptionFileChange(conn *websocket.Conn, projectName string) error{
  532. getLocalFileListDir = fmt.Sprint(config.LocalWorkSpaceDir+gobalLoginUserName+"\\"+projectName+"\\")
  533. keyPrefix := gobalLoginUserName+"\\"+projectName+"\\"
  534. //定期校验缓存的本地文件状态
  535. go func() {
  536. for true {
  537. time.Sleep(time.Duration(5)*time.Minute)
  538. dataMap,err := etcdclient.QueryWithPrefix(keyPrefix)
  539. if err != nil {
  540. log.Println(err)
  541. continue
  542. }
  543. if dataMap!=nil && len(dataMap)>0{
  544. for k,_ := range dataMap {
  545. if !fileExist(config.LocalWorkSpaceDir+k){
  546. err = etcdclient.DeleteWithPrefix(k)
  547. if err != nil {
  548. log.Println(err)
  549. }
  550. }
  551. }
  552. }
  553. }
  554. }()
  555. for true {
  556. //优先etcd查询
  557. dataMap,err := etcdclient.QueryWithPrefix(keyPrefix)
  558. if err != nil {
  559. log.Println(err)
  560. return err
  561. }
  562. if dataMap!=nil && len(dataMap)>0{
  563. cacheMap := make(map[string] string)
  564. for k,v := range dataMap {
  565. cacheMap[strings.Replace(k,gobalLoginUserName+"\\"+projectName+"\\","",1)]=v
  566. }
  567. mapByte,err:=json.Marshal(cacheMap)
  568. if err != nil {
  569. log.Println(err)
  570. return err
  571. }
  572. if err := conn.WriteMessage(websocket.TextMessage, mapByte); err != nil {
  573. log.Println(err)
  574. return err
  575. }
  576. time.Sleep(time.Duration(1)*time.Minute)
  577. continue
  578. }
  579. // 不存在则初始化进etcd
  580. err =filepath.Walk(getLocalFileListDir,walkfunc)
  581. //路径错误
  582. if err != nil {
  583. log.Println(err)
  584. if err := conn.WriteMessage(websocket.TextMessage, []byte("{}")); err != nil {
  585. log.Println(err)
  586. return err
  587. }
  588. time.Sleep(time.Duration(1)*time.Minute)
  589. continue
  590. }
  591. mapByte,err:=json.Marshal(gobalFileMap)
  592. if err != nil {
  593. log.Println(err)
  594. return err
  595. }
  596. if err := conn.WriteMessage(websocket.TextMessage, mapByte); err != nil {
  597. log.Println(err)
  598. return err
  599. }
  600. cacheMap := make(map[string] string)
  601. for k,v := range gobalFileMap {
  602. k := strings.Replace(k,config.LocalWorkSpaceDir,"",1)
  603. cacheMap[k]=v
  604. }
  605. //异步缓存
  606. //go func() {
  607. err = etcdclient.BatchAdd(cacheMap)
  608. if err != nil {
  609. log.Println(err)
  610. }
  611. //}()
  612. //log.Println("检查本地目录文件变更状态,执行睡眠时间1分钟")
  613. //清空gobalFileMap
  614. gobalFileMap = make(map[string] string)
  615. time.Sleep(time.Duration(1)*time.Minute)
  616. }
  617. return nil
  618. }
  619. /**
  620. TODO 文件变更通知
  621. */
  622. func FileChangeNotify(){
  623. }
  624. /**
  625. TODO 监视文件变动
  626. */
  627. func WatchFile(filePaths string) error{
  628. if len(filePaths)==0{
  629. //TODO
  630. return nil
  631. }
  632. files := strings.Split(filePaths,";")
  633. for _,file := range files{
  634. err :=config.GobalWatch.Add(file)
  635. if err != nil {
  636. log.Println(err)
  637. }
  638. log.Println("文件[ "+file+" ]添加监听事件成功")
  639. }
  640. return nil
  641. }
  642. /**
  643. 打开方式
  644. */
  645. func OpenFileWith(filePath string) error{
  646. //判断文件有效性
  647. _,err := os.Stat(filePath)
  648. if err!=nil{
  649. return err
  650. }
  651. //filePath = strings.Replace(filePath," ","~1",1)
  652. cmd := exec.Command("rundll32.exe","shell32.dll,OpenAs_RunDLL",filePath);
  653. err =cmd.Run()
  654. if err!=nil{
  655. log.Println(err)
  656. return err
  657. }
  658. return nil
  659. }
  660. /**
  661. 手动检查软件更新
  662. 0:不强制更新
  663. 1:强制更新
  664. */
  665. func CheckForUpdates(forceUpdate string) error{
  666. tszdir :=os.Getenv("TSZDIR")
  667. //空格路径处理
  668. ipfsPath=strings.Replace(os.Getenv("IPFS-PATH"),"\"","",1)+"\\stop.vbs"
  669. //判断文件有效性
  670. _,err := os.Stat(tszdir+config.UpdaterName)
  671. if err!=nil{
  672. return err
  673. }
  674. cmd := exec.Command(tszdir+config.UpdaterName,"/justcheck");
  675. err =cmd.Run()
  676. if err!=nil{
  677. log.Println(err)
  678. return err
  679. }
  680. cmd = exec.Command(tszdir+config.UpdaterName,"/checknow");
  681. err =cmd.Run()
  682. if err!=nil{
  683. log.Println(err)
  684. return err
  685. }
  686. //检测到更新 kill所有客户端进程
  687. log.Println("close all process")
  688. cmd = exec.Command("cmd.exe","/c",ipfsPath);
  689. err =cmd.Run()
  690. if err!=nil{
  691. log.Println(err)
  692. return err
  693. }
  694. return nil
  695. }
  696. func walkfunc(path string, info os.FileInfo, err error) error {
  697. if info == nil{
  698. return nil
  699. }
  700. if info.IsDir()==false{
  701. sh := shell.NewShell(config.GobalIpfsUrl)
  702. file,err :=os.Open(path)
  703. if err != nil{
  704. log.Println(err)
  705. return err
  706. }
  707. defer file.Close()
  708. hash,err :=sh.Add(file)
  709. if err != nil {
  710. log.Println(err)
  711. return err
  712. }
  713. dir :=strings.Replace(fmt.Sprint(path),fmt.Sprint(getLocalFileListDir),"",1)
  714. gobalFileMap[dir]=hash
  715. }
  716. return nil
  717. }