public_host
4 years ago
6 changed files with 350 additions and 2 deletions
-
6.gitignore
-
15README.md
-
2build/init.bat
-
2build/make-key.bat
-
2build/upload.bat
-
325main.go
@ -1,2 +1,17 @@ |
|||
# qcloudcos |
|||
|
|||
```sh |
|||
|
|||
# 生成key |
|||
> qcloudcos -op make-key |
|||
|
|||
# 设置key |
|||
> qcloudcos -op set-key |
|||
|
|||
# 上传文件夹 |
|||
> qcloudcos -op upload -path ./foo |
|||
|
|||
# 查看文件夹信息 |
|||
> qcloudcos -op list |
|||
|
|||
``` |
@ -0,0 +1,2 @@ |
|||
%~dp0qcloudcos -op set-key |
|||
pause |
@ -0,0 +1,2 @@ |
|||
%~dp0qcloudcos -op make-key |
|||
pause |
@ -0,0 +1,2 @@ |
|||
%~dp0qcloudcos -op upload -path %1 |
|||
pause |
@ -0,0 +1,325 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"bytes" |
|||
"context" |
|||
"encoding/base64" |
|||
"encoding/json" |
|||
"errors" |
|||
"flag" |
|||
"fmt" |
|||
"github.com/AlecAivazis/survey" |
|||
"github.com/tencentyun/cos-go-sdk-v5" |
|||
"github.com/wailovet/osmanthuswine/src/helper" |
|||
"io/ioutil" |
|||
"net/http" |
|||
"net/url" |
|||
"os" |
|||
"os/exec" |
|||
"os/user" |
|||
"path/filepath" |
|||
"runtime" |
|||
"strings" |
|||
) |
|||
|
|||
var config TencentYunConfig |
|||
|
|||
var op string |
|||
var path string |
|||
var key string |
|||
|
|||
func loadKey() { |
|||
homePath, err := home() |
|||
if err != nil { |
|||
fmt.Println("错误 102: ", err) |
|||
return |
|||
} |
|||
keyFile := filepath.Join(homePath, ".qcloud-key") |
|||
data, _ := ioutil.ReadFile(keyFile) |
|||
if string(data) == "" { |
|||
fmt.Println("错误 204 找不到key,请使用使用set-key进行初始化.") |
|||
return |
|||
} |
|||
key = string(data) |
|||
} |
|||
|
|||
func initKey() { |
|||
|
|||
if key == "" { |
|||
fmt.Println("key is empty!") |
|||
os.Exit(1) |
|||
} |
|||
var err error |
|||
var dekey []byte |
|||
dekey, err = base64.StdEncoding.DecodeString(key) |
|||
if err != nil { |
|||
fmt.Println("错误 201:", err) |
|||
os.Exit(1) |
|||
} |
|||
|
|||
dekey, err = helper.DefaultAesDecrypt(dekey) |
|||
if err != nil { |
|||
fmt.Println("错误 202:", err) |
|||
os.Exit(1) |
|||
} |
|||
err = json.Unmarshal(dekey, &config) |
|||
if err != nil { |
|||
fmt.Println("错误 203:", err) |
|||
os.Exit(1) |
|||
} |
|||
} |
|||
|
|||
func main() { |
|||
|
|||
helper.AesKey = []byte("3136352472abcdef") |
|||
flag.StringVar(&op, "op", "", "操作:make-key[生成密钥] | set-key[设置密钥] | upload [上传文件] | list [获取文件]") |
|||
flag.StringVar(&path, "path", "", "上传目录") |
|||
flag.StringVar(&key, "key", "", "key") |
|||
flag.Parse() |
|||
|
|||
switch op { |
|||
case "set-key": |
|||
key = askText("输入key") |
|||
initKey() |
|||
_, err := getTencentYunCosFiles("") |
|||
if err != nil { |
|||
fmt.Println("key error 101:", err) |
|||
return |
|||
} |
|||
|
|||
homePath, err := home() |
|||
if err != nil { |
|||
fmt.Println("错误 102:", err) |
|||
return |
|||
} |
|||
keyFile := filepath.Join(homePath, ".qcloud-key") |
|||
err = ioutil.WriteFile(keyFile, []byte(key), 0644) |
|||
if err != nil { |
|||
fmt.Println("错误 103:", err) |
|||
return |
|||
} |
|||
|
|||
fmt.Println("完成!") |
|||
case "make-key": |
|||
config.SecretID = askText("输入SecretID") |
|||
config.SecretKey = askText("输入SecretKey") |
|||
config.BucketURL = askText("输入BucketURL") |
|||
config.Root = askText("输入Root") |
|||
|
|||
mkey, err := helper.DefaultAesEncrypt([]byte(helper.JsonEncode(config))) |
|||
if err != nil { |
|||
fmt.Println("错误 104:", err) |
|||
return |
|||
} |
|||
mkey = []byte(base64.StdEncoding.EncodeToString(mkey)) |
|||
fmt.Println("key:", string(mkey), " ==> ", "key.txt") |
|||
_ = ioutil.WriteFile("key.txt", mkey, 0644) |
|||
os.Exit(0) |
|||
case "upload": |
|||
loadKey() |
|||
initKey() |
|||
|
|||
if path != "" { |
|||
url := UploadDir(path) |
|||
fmt.Println("url:", url) |
|||
} else { |
|||
flag.Usage() |
|||
} |
|||
case "list": |
|||
loadKey() |
|||
initKey() |
|||
for { |
|||
data, err := getTencentYunCosFiles(path) |
|||
if err != nil { |
|||
fmt.Println("错误 106:", err) |
|||
return |
|||
} |
|||
//for e := range data.CommonPrefixes {
|
|||
// fmt.Println(data.CommonPrefixes[e])
|
|||
//}
|
|||
var files []string |
|||
for e := range data.Contents { |
|||
files = append(files, data.Contents[e].Key) |
|||
} |
|||
_, menu := askSelect("Path:"+path, append([]string{".."}, append(data.CommonPrefixes, files...)...)...) |
|||
if menu == ".." { |
|||
pathSplit := strings.Split(path, "/") |
|||
if len(pathSplit) > 1 { |
|||
path = strings.Join(pathSplit[0:len(pathSplit)-1], "/") |
|||
} else { |
|||
path = "" |
|||
} |
|||
} else { |
|||
path = menu |
|||
} |
|||
} |
|||
|
|||
default: |
|||
flag.Usage() |
|||
} |
|||
} |
|||
|
|||
type TencentYunConfig struct { |
|||
SecretID string |
|||
SecretKey string |
|||
SessionToken string |
|||
BucketURL string |
|||
Root string |
|||
} |
|||
|
|||
var client *cos.Client |
|||
|
|||
func getTencentYunConf(c *TencentYunConfig) *cos.Client { |
|||
if client == nil { |
|||
BucketURL, _ := url.Parse(c.BucketURL) |
|||
b := &cos.BaseURL{ |
|||
BucketURL: BucketURL, |
|||
} |
|||
// 1.永久密钥
|
|||
client = cos.NewClient(b, &http.Client{ |
|||
Transport: &cos.AuthorizationTransport{ |
|||
SecretID: c.SecretID, |
|||
SecretKey: c.SecretKey, |
|||
}, |
|||
}) |
|||
} |
|||
|
|||
return client |
|||
} |
|||
|
|||
func getTencentYunCosFiles(prefix string) (*cos.BucketGetResult, error) { |
|||
|
|||
// 1.永久密钥
|
|||
client := getTencentYunConf(&config) |
|||
|
|||
res, _, err := client.Bucket.Get(context.Background(), &cos.BucketGetOptions{ |
|||
Prefix: prefix, |
|||
Delimiter: "/", |
|||
}) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
return res, nil |
|||
} |
|||
|
|||
func UploadDir(fpath string, qpaths ...string) string { |
|||
qpath := "" |
|||
if len(qpaths) > 0 { |
|||
qpath = qpaths[0] |
|||
} else { |
|||
separator := "/" |
|||
if runtime.GOOS == "windows" { |
|||
separator = `\` |
|||
} |
|||
separatordir := strings.Split(fpath, separator) |
|||
if len(separatordir) > 0 { |
|||
qpath = separatordir[len(separatordir)-1] |
|||
} |
|||
} |
|||
client := getTencentYunConf(&config) |
|||
|
|||
files, _ := ioutil.ReadDir(fpath) |
|||
for _, f := range files { |
|||
if f.Name()[0] == '.' { |
|||
continue |
|||
} |
|||
if f.IsDir() { |
|||
UploadDir(filepath.Join(fpath, f.Name()), filepath.Join(qpath, f.Name())) |
|||
} else { |
|||
filename := filepath.Join(fpath, f.Name()) |
|||
fmt.Print("上传:", filename, " ==> ", filepath.Join(config.Root, filename), " ") |
|||
_, err := client.Object.PutFromFile(context.Background(), strings.Replace(filepath.Join(config.Root, qpath, f.Name()), `\`, `/`, -1), filename, nil) |
|||
if err != nil { |
|||
fmt.Println("错误 105:", err) |
|||
} else { |
|||
fmt.Println("完成") |
|||
} |
|||
} |
|||
} |
|||
|
|||
return config.BucketURL + "/" + strings.Replace(filepath.Join(config.Root, qpath), `\`, `/`, -1) |
|||
} |
|||
|
|||
func askSelect(title string, v ...string) (int, string) { |
|||
|
|||
result := -1 |
|||
prompt := &survey.Select{ |
|||
Message: title, |
|||
Options: v, |
|||
} |
|||
|
|||
err := survey.AskOne(prompt, &result) |
|||
if err != nil { |
|||
return 0, "" |
|||
} |
|||
|
|||
if result == -1 { |
|||
return askSelect(title, v...) |
|||
} |
|||
return result, v[result] |
|||
} |
|||
|
|||
func askText(title string) string { |
|||
result := "" |
|||
prompt := &survey.Input{ |
|||
Message: title, |
|||
} |
|||
survey.AskOne(prompt, &result) |
|||
|
|||
if result == "" { |
|||
fmt.Println("不允许为空") |
|||
return askText(title) |
|||
} |
|||
return result |
|||
} |
|||
func home() (string, error) { |
|||
user, err := user.Current() |
|||
if nil == err { |
|||
return user.HomeDir, nil |
|||
} |
|||
|
|||
// cross compile support
|
|||
|
|||
if "windows" == runtime.GOOS { |
|||
return homeWindows() |
|||
} |
|||
|
|||
// Unix-like system, so just assume Unix
|
|||
return homeUnix() |
|||
} |
|||
|
|||
func homeUnix() (string, error) { |
|||
// First prefer the HOME environmental variable
|
|||
if home := os.Getenv("HOME"); home != "" { |
|||
return home, nil |
|||
} |
|||
|
|||
// If that fails, try the shell
|
|||
var stdout bytes.Buffer |
|||
cmd := exec.Command("sh", "-c", "eval echo ~$USER") |
|||
cmd.Stdout = &stdout |
|||
if err := cmd.Run(); err != nil { |
|||
return "", err |
|||
} |
|||
|
|||
result := strings.TrimSpace(stdout.String()) |
|||
if result == "" { |
|||
return "", errors.New("blank output when reading home directory") |
|||
} |
|||
|
|||
return result, nil |
|||
} |
|||
|
|||
func homeWindows() (string, error) { |
|||
drive := os.Getenv("HOMEDRIVE") |
|||
path := os.Getenv("HOMEPATH") |
|||
home := drive + path |
|||
if drive == "" || path == "" { |
|||
home = os.Getenv("USERPROFILE") |
|||
} |
|||
if home == "" { |
|||
return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank") |
|||
} |
|||
|
|||
return home, nil |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue