upgrade
This commit is contained in:
parent
24fb25692f
commit
98aa5b7de7
0
cmd/upgrade/build.sh
Normal file
0
cmd/upgrade/build.sh
Normal file
5
cmd/upgrade/build_linux.bat
Normal file
5
cmd/upgrade/build_linux.bat
Normal file
@ -0,0 +1,5 @@
|
||||
SET CGO_ENABLED=0
|
||||
SET GOOS=linux
|
||||
SET GOARCH=amd64
|
||||
|
||||
go build -o update main.go
|
167
cmd/upgrade/main.go
Normal file
167
cmd/upgrade/main.go
Normal file
@ -0,0 +1,167 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go_dreamfactory/cmd/upgrade/tools"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// func main() {
|
||||
// http.HandleFunc("/download", FileDownload)
|
||||
// http.HandleFunc("/upload", FileUpload)
|
||||
|
||||
// log.Print("http server start")
|
||||
// if err := http.ListenAndServe(":8910", nil); err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
// }
|
||||
|
||||
func FileUpload(w http.ResponseWriter, r *http.Request) {
|
||||
//获取文件流,第三个返回值是错误对象
|
||||
file, header, _ := r.FormFile("file")
|
||||
//读取文件流为[]byte
|
||||
b, _ := ioutil.ReadAll(file)
|
||||
//把文件保存到指定位置
|
||||
ioutil.WriteFile("/opt/upgrade", b, 0777)
|
||||
//输出上传时文件名
|
||||
fmt.Println("上传文件名:", header.Filename)
|
||||
}
|
||||
|
||||
func FileDownload(w http.ResponseWriter, r *http.Request) {
|
||||
filename := "E:\\projects\\workspace\\go_dreamfactory\\cmd\\v2\\RobotGUI.exe"
|
||||
|
||||
file, _ := os.Open(filename)
|
||||
defer file.Close()
|
||||
|
||||
fileHeader := make([]byte, 512)
|
||||
file.Read(fileHeader)
|
||||
|
||||
fileStat, _ := file.Stat()
|
||||
|
||||
w.Header().Set("Content-Disposition", "attachment; filename="+filename)
|
||||
w.Header().Set("Content-Type", http.DetectContentType(fileHeader))
|
||||
w.Header().Set("Content-Length", strconv.FormatInt(fileStat.Size(), 10))
|
||||
|
||||
file.Seek(0, 0)
|
||||
io.Copy(w, file)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
//go:embed views/*
|
||||
var f embed.FS
|
||||
|
||||
var version = "0.0.1"
|
||||
|
||||
func main() {
|
||||
|
||||
host := flag.String("host", "10.0.0.9", "Host")
|
||||
port := flag.String("port", "8080", "Port")
|
||||
uploadsDir := flag.String("uploadsDir", "./uploads", "上传文件存储地址")
|
||||
wwwDir := flag.String("wwwDir", "./www", "www服务地址,即解压地址")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
r := gin.Default()
|
||||
r.Static("/prd", "./www")
|
||||
tmpl := template.Must(template.New("").ParseFS(f, "views/*"))
|
||||
r.SetHTMLTemplate(tmpl)
|
||||
|
||||
r.GET("/version", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"version": version,
|
||||
})
|
||||
})
|
||||
|
||||
r.GET("/", func(c *gin.Context) {
|
||||
fmt.Println(tmpl.DefinedTemplates())
|
||||
c.HTML(http.StatusOK, "index.html", nil)
|
||||
})
|
||||
|
||||
r.POST("/upload", func(c *gin.Context) {
|
||||
f, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
//从上传的文件名获取到版本号
|
||||
s := strings.SplitN(f.Filename, "-", 2)
|
||||
if len(s) != 2 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "上传的文件名中没有包含版本号 eg. update.zip-0.0.1",
|
||||
})
|
||||
return
|
||||
}
|
||||
version = s[1] //设置版本号
|
||||
|
||||
dst := path.Join(*uploadsDir, f.Filename)
|
||||
err = c.SaveUploadedFile(f, dst)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
_, err = tools.Unzip(dst, *wwwDir)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"msg": "upload success",
|
||||
"url": strings.Join([]string{"http://" + *host + ":" + *port, "/prd/", strings.Split(f.Filename, ".")[0], "/index.html"}, ""),
|
||||
})
|
||||
})
|
||||
|
||||
r.GET("/dirs", func(c *gin.Context) {
|
||||
dir, err := ioutil.ReadDir(*wwwDir)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
type Item struct {
|
||||
Name string `json:"name"`
|
||||
Url string `json:"url"`
|
||||
DateTime string `json:"dateTime"`
|
||||
}
|
||||
|
||||
var dirs []Item
|
||||
for _, f := range dir {
|
||||
// if f.IsDir() && len(f.Name()) > 0 && f.Name() != "__MACOSX" {
|
||||
dirs = append(dirs, Item{
|
||||
Name: f.Name(),
|
||||
Url: strings.Join([]string{"http://" + *host + ":" + *port, "/prd/", f.Name()}, ""),
|
||||
DateTime: f.ModTime().Format(time.RFC3339),
|
||||
})
|
||||
// }
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"dirs": dirs,
|
||||
})
|
||||
})
|
||||
|
||||
err := r.Run("0.0.0.0:" + *port)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
0
cmd/upgrade/readme.md
Normal file
0
cmd/upgrade/readme.md
Normal file
125
cmd/upgrade/tools/gz.go
Normal file
125
cmd/upgrade/tools/gz.go
Normal file
@ -0,0 +1,125 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func UnGz(tarFile, dest string) error {
|
||||
srcFile, err := os.Open(tarFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer srcFile.Close()
|
||||
gr, err := gzip.NewReader(srcFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer gr.Close()
|
||||
tr := tar.NewReader(gr)
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
filename := dest + hdr.Name
|
||||
file, err := createFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
io.Copy(file, tr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createFile(name string) (*os.File, error) {
|
||||
err := os.MkdirAll(string([]rune(name)[0:strings.LastIndex(name, "/")]), 0755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return os.Create(name)
|
||||
}
|
||||
|
||||
func UnGzip(tarName, xpath string) (err error) {
|
||||
tarFile, err := os.Open(tarName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
err = tarFile.Close()
|
||||
}()
|
||||
|
||||
os.Mkdir(xpath, 0755)
|
||||
|
||||
absPath, err := filepath.Abs(xpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tr := tar.NewReader(tarFile)
|
||||
if strings.HasSuffix(tarName, ".gz") || strings.HasSuffix(tarName, ".gzip") {
|
||||
gz, err := gzip.NewReader(tarFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer gz.Close()
|
||||
tr = tar.NewReader(gz)
|
||||
}
|
||||
|
||||
// untar each segment
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// determine proper file path info
|
||||
finfo := hdr.FileInfo()
|
||||
fileName := hdr.Name
|
||||
if filepath.IsAbs(fileName) {
|
||||
fmt.Printf("removing / prefix from %s\n", fileName)
|
||||
fileName, err = filepath.Rel("/", fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
absFileName := filepath.Join(absPath, fileName)
|
||||
|
||||
if finfo.Mode().IsDir() {
|
||||
if err := os.MkdirAll(absFileName, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// create new file with original file mode
|
||||
file, err := os.OpenFile(absFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, finfo.Mode().Perm())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("x %s\n", absFileName)
|
||||
n, cpErr := io.Copy(file, tr)
|
||||
if closeErr := file.Close(); closeErr != nil { // close file immediately
|
||||
return err
|
||||
}
|
||||
if cpErr != nil {
|
||||
return cpErr
|
||||
}
|
||||
if n != finfo.Size() {
|
||||
return fmt.Errorf("unexpected bytes written: wrote %d, want %d", n, finfo.Size())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
54
cmd/upgrade/tools/zip.go
Normal file
54
cmd/upgrade/tools/zip.go
Normal file
@ -0,0 +1,54 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Unzip(src string, dest string) ([]string, error) {
|
||||
var filenames []string
|
||||
r, err := zip.OpenReader(src)
|
||||
if err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
for _, f := range r.File {
|
||||
// Store filename/path for returning and using later on
|
||||
fpath := filepath.Join(dest, f.Name)
|
||||
// Check for ZipSlip. More Info: http://bit.ly/2MsjAWE
|
||||
if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
|
||||
return filenames, fmt.Errorf("%s: illegal file path", fpath)
|
||||
}
|
||||
filenames = append(filenames, fpath)
|
||||
if f.FileInfo().IsDir() {
|
||||
// Make Folder
|
||||
os.MkdirAll(fpath, os.ModePerm)
|
||||
continue
|
||||
}
|
||||
// Make File
|
||||
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
if err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
_, err = io.Copy(outFile, rc)
|
||||
// Close the file without defer to close before next iteration of loop
|
||||
outFile.Close()
|
||||
rc.Close()
|
||||
if err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
}
|
||||
return filenames, nil
|
||||
}
|
69
cmd/upgrade/views/index.html
Normal file
69
cmd/upgrade/views/index.html
Normal file
@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>上传</title>
|
||||
<!-- import Vue.js -->
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.6/vue.min.js"></script>
|
||||
<!-- import stylesheet -->
|
||||
<link href="https://cdn.bootcdn.net/ajax/libs/iview/3.5.5-rc.1/styles/iview.min.css" rel="stylesheet">
|
||||
<!-- import iView -->
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/iview/3.5.5-rc.1/iview.min.js"></script>
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
|
||||
<style>
|
||||
#app {
|
||||
margin: 20px 40px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
|
||||
<h1>上传原型,获取永久在线浏览地址</h1>
|
||||
|
||||
<upload type="drag" action="/upload" paste="true" accept=".zip" :on-success="handleSuccess">
|
||||
<div style="padding: 20px 0">
|
||||
<icon type="ios-cloud-upload" size="52" style="color: #3399ff"></icon>
|
||||
<p>点击或者拖拽上传</p>
|
||||
</div>
|
||||
</upload>
|
||||
|
||||
<alert type="success" v-for="url in zips">
|
||||
浏览地址:${ url }
|
||||
</alert>
|
||||
|
||||
|
||||
|
||||
<strong>历史prd:</strong>
|
||||
<br><br>
|
||||
<list border>
|
||||
<list-item v-for="dir in dirs">
|
||||
<a :href="dir.url" target="_blank">${ dir.name }</a> <span>${ dir.dateTime}</span>
|
||||
</list-item>
|
||||
</list>
|
||||
</div>
|
||||
<script>
|
||||
new Vue({
|
||||
el: "#app",
|
||||
delimiters: ['${', '}'],
|
||||
data: {
|
||||
zips: [],
|
||||
dirs: [],
|
||||
},
|
||||
methods: {
|
||||
handleSuccess(response, file, fileList) {
|
||||
this.zips.push(response.url)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
axios.get("/dirs").then((res) => {
|
||||
this.dirs = res.data.dirs
|
||||
})
|
||||
},
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user