完成了分享下载全部流程
This commit is contained in:
@@ -14,7 +14,7 @@ type BaseCardService struct{}
|
||||
var BaseCard = &BaseCardService{}
|
||||
|
||||
func (*BaseCardService) Create(db *gorm.DB, baseCard models.BaseCard) {
|
||||
repo.BaseCard.Create(db, &baseCard)
|
||||
repo.BaseCard.CreateOrSave(db, &baseCard)
|
||||
}
|
||||
|
||||
func (*BaseCardService) Update(db *gorm.DB, updateCard models.BaseCard) {
|
||||
|
||||
+145
-1
@@ -1,9 +1,17 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"fyne.io/fyne/v2/data/binding"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
"work_cation/cfg"
|
||||
"work_cation/models"
|
||||
)
|
||||
|
||||
@@ -14,7 +22,13 @@ var Client = &ClientService{}
|
||||
|
||||
func (c *ClientService) GetUser(online *models.Online) (*models.Users, error) {
|
||||
var user models.Users
|
||||
resp, err := http.Get(online.Url("/user"))
|
||||
ctx, carnal := context.WithTimeout(context.TODO(), time.Millisecond*500)
|
||||
defer carnal()
|
||||
res, err := http.NewRequestWithContext(ctx, "", online.Url("/user"), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -29,3 +43,133 @@ func (c *ClientService) GetUser(online *models.Online) (*models.Users, error) {
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (c *ClientService) GetCards(online *models.Online) ([]models.BaseCard, error) {
|
||||
var cards []models.BaseCard
|
||||
ctx, carnal := context.WithTimeout(context.TODO(), time.Millisecond*500)
|
||||
defer carnal()
|
||||
res, err := http.NewRequestWithContext(ctx, "", online.Url("/cards"), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(data, &cards)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cards, nil
|
||||
}
|
||||
|
||||
func (c *ClientService) Download(online *models.Online, uuid string, progress binding.Float) error {
|
||||
|
||||
resp, err := http.Get(online.Url("/download/card/" + uuid))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
downloadFile := filepath.Join(cfg.T.CardDir, fmt.Sprintf("%s.zip", uuid))
|
||||
_, err = os.Stat(downloadFile)
|
||||
if err == nil {
|
||||
os.Remove(downloadFile)
|
||||
}
|
||||
|
||||
file, err := os.Create(downloadFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
r := Rr{
|
||||
file: file,
|
||||
tot: resp.ContentLength,
|
||||
progress: 0,
|
||||
oneUp: 0,
|
||||
progressBind: progress,
|
||||
}
|
||||
|
||||
_, err = io.Copy(&r, resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 解压
|
||||
destDir := filepath.Join(cfg.T.CardDir, uuid)
|
||||
_ = os.RemoveAll(destDir)
|
||||
if err = unzipFile(downloadFile, destDir); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = os.Remove(downloadFile)
|
||||
return nil
|
||||
}
|
||||
|
||||
type Rr struct {
|
||||
file *os.File
|
||||
tot int64
|
||||
progress int64
|
||||
|
||||
oneUp int
|
||||
progressBind binding.Float
|
||||
}
|
||||
|
||||
func (r *Rr) Write(p []byte) (n int, err error) {
|
||||
n, err = r.file.Write(p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r.progress += int64(n)
|
||||
|
||||
nowUp := int(r.progress * 100 / r.tot)
|
||||
if nowUp != r.oneUp {
|
||||
r.progressBind.Set(float64(nowUp))
|
||||
r.oneUp = nowUp
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func unzipFile(zipFile, destDir string) error {
|
||||
// 打开ZIP文件
|
||||
r, err := zip.OpenReader(zipFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer r.Close()
|
||||
// 创建目标目录
|
||||
err = os.MkdirAll(destDir, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 遍历ZIP文件中的文件并解压缩到目标目录
|
||||
for _, f := range r.File {
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 创建文件
|
||||
path := filepath.Join(destDir, f.Name)
|
||||
if f.FileInfo().IsDir() {
|
||||
os.MkdirAll(path, os.ModePerm)
|
||||
} else {
|
||||
// 创建文件
|
||||
file, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(file, rc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
rc.Close()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func (*erlangCardService) Create(erlangCard *models.ErlangCards) error {
|
||||
return global.DB.Transaction(func(tx *gorm.DB) error {
|
||||
var baseCard = erlangCard.BaseCard
|
||||
|
||||
err = repo.BaseCard.Create(global.DB, &baseCard)
|
||||
err = repo.BaseCard.CreateOrSave(global.DB, &baseCard)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
+1
-1
@@ -49,6 +49,6 @@ func (*ExecFileService) Create(info *models.ExecFiles, chooseDir string) error {
|
||||
}
|
||||
return global.DB.Transaction(func(tx *gorm.DB) error {
|
||||
var baseCard = info.BaseCard
|
||||
return repo.BaseCard.Create(tx, &baseCard)
|
||||
return repo.BaseCard.CreateOrSave(tx, &baseCard)
|
||||
})
|
||||
}
|
||||
|
||||
+80
-1
@@ -1,10 +1,15 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"work_cation/cfg"
|
||||
"work_cation/global"
|
||||
"work_cation/repo"
|
||||
@@ -52,11 +57,35 @@ func (s *serverService) StatusOffline() error {
|
||||
}
|
||||
|
||||
func (s *serverService) StartListenServer() error {
|
||||
router := gin.New()
|
||||
router := gin.Default()
|
||||
router.GET("/user", func(c *gin.Context) {
|
||||
user := repo.User.GetUserInfo(global.DB)
|
||||
c.JSON(200, user)
|
||||
})
|
||||
router.GET("/cards", func(c *gin.Context) {
|
||||
cards := repo.BaseCard.FindAll(global.DB)
|
||||
c.JSON(200, cards)
|
||||
})
|
||||
router.GET("/download/card/:uuid", func(c *gin.Context) {
|
||||
uuid := c.Param("uuid")
|
||||
card := repo.BaseCard.Find(global.DB, uuid)
|
||||
fmt.Println("card:", card)
|
||||
if card.UUID == "" {
|
||||
c.JSON(404, nil)
|
||||
return
|
||||
}
|
||||
cardPath := filepath.Join(cfg.T.CardDir, card.UUID)
|
||||
|
||||
// 设置响应头
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s.zip", uuid))
|
||||
c.Header("Content-Type", "application/zip")
|
||||
|
||||
err := zipFolder(cardPath, c.Writer)
|
||||
if err != nil {
|
||||
c.JSON(500, err)
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: cfg.T.ServerAddr,
|
||||
@@ -71,3 +100,53 @@ func (s *serverService) StartListenServer() error {
|
||||
s.server = srv
|
||||
return nil
|
||||
}
|
||||
|
||||
func zipFolder(folderPath string, zipFile io.Writer) error {
|
||||
zipWriter := zip.NewWriter(zipFile)
|
||||
defer zipWriter.Close()
|
||||
err := filepath.Walk(folderPath, func(filePath string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header.Name, err = filepath.Rel(folderPath, filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
header.Name += "/"
|
||||
} else {
|
||||
header.Method = zip.Deflate
|
||||
}
|
||||
|
||||
writer, err := zipWriter.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(writer, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+16
-15
@@ -4,13 +4,14 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/grandcat/zeroconf"
|
||||
"time"
|
||||
"slices"
|
||||
"work_cation/cfg"
|
||||
"work_cation/models"
|
||||
)
|
||||
|
||||
type zeroconfService struct {
|
||||
server *zeroconf.Server
|
||||
server *zeroconf.Server
|
||||
onlines []models.Online
|
||||
}
|
||||
|
||||
var Zeroconf = &zeroconfService{}
|
||||
@@ -37,31 +38,31 @@ func (s *zeroconfService) Close() {
|
||||
}
|
||||
|
||||
// FindService 查找被发现服务
|
||||
func (s *zeroconfService) FindService() (chan *models.Online, error) {
|
||||
func (s *zeroconfService) FindService() ([]models.Online, error) {
|
||||
return s.onlines, nil
|
||||
}
|
||||
|
||||
func (s *zeroconfService) StartFindService() error {
|
||||
resolver, err := zeroconf.NewResolver(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
allEntries := make(chan *zeroconf.ServiceEntry)
|
||||
useEntries := make(chan *models.Online)
|
||||
|
||||
go func(results <-chan *zeroconf.ServiceEntry) {
|
||||
for entry := range results {
|
||||
fmt.Println(entry.AddrIPv4, entry.ServiceInstanceName())
|
||||
if entry.ServiceInstanceName() == fmt.Sprintf("%s._http._tcp.local.", cfg.T.ZeroconfKey) {
|
||||
online, err := models.NewOnline(entry)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
useEntries <- online
|
||||
delOnlines := slices.DeleteFunc(s.onlines, func(item models.Online) bool {
|
||||
return item.ID == online.ID
|
||||
})
|
||||
s.onlines = append(delOnlines, *online)
|
||||
}
|
||||
}
|
||||
}(allEntries)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
err = resolver.Browse(ctx, "_http._tcp", "local.", allEntries)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, err
|
||||
}
|
||||
time.AfterFunc(10*time.Second, cancel)
|
||||
return useEntries, nil
|
||||
err = resolver.Browse(context.Background(), "_http._tcp", "local.", allEntries)
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user