2022-03-09 12:30:56 +00:00
|
|
|
package _189
|
|
|
|
|
|
|
|
import (
|
2022-04-03 09:56:21 +00:00
|
|
|
"bytes"
|
2022-03-09 12:30:56 +00:00
|
|
|
"crypto/md5"
|
2022-04-03 09:56:21 +00:00
|
|
|
"encoding/base64"
|
2022-03-09 12:30:56 +00:00
|
|
|
"encoding/hex"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
2022-04-03 09:56:21 +00:00
|
|
|
"math"
|
2022-03-09 12:30:56 +00:00
|
|
|
"net/http"
|
2022-04-03 09:56:21 +00:00
|
|
|
"net/url"
|
2022-03-09 12:30:56 +00:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/Xhofe/alist/conf"
|
|
|
|
"github.com/Xhofe/alist/drivers/base"
|
|
|
|
"github.com/Xhofe/alist/model"
|
|
|
|
"github.com/Xhofe/alist/utils"
|
|
|
|
"github.com/go-resty/resty/v2"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
base.RegisterDriver(new(Cloud189))
|
|
|
|
}
|
|
|
|
|
|
|
|
type Cloud189 struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) Config() base.DriverConfig {
|
|
|
|
return base.DriverConfig{
|
|
|
|
Name: "189CloudPC",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) Items() []base.Item {
|
|
|
|
return []base.Item{
|
|
|
|
{
|
|
|
|
Name: "username",
|
|
|
|
Label: "username",
|
|
|
|
Type: base.TypeString,
|
|
|
|
Required: true,
|
|
|
|
Description: "account username/phone number",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "password",
|
|
|
|
Label: "password",
|
|
|
|
Type: base.TypeString,
|
|
|
|
Required: true,
|
|
|
|
Description: "account password",
|
|
|
|
},
|
|
|
|
{
|
2022-04-03 09:56:21 +00:00
|
|
|
Name: "root_folder",
|
|
|
|
Label: "root folder file_id",
|
|
|
|
Type: base.TypeString,
|
2022-03-09 12:30:56 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "internal_type",
|
|
|
|
Label: "189cloud type",
|
|
|
|
Type: base.TypeSelect,
|
|
|
|
Required: true,
|
|
|
|
Values: "Personal,Family",
|
|
|
|
},
|
|
|
|
{
|
2022-04-03 09:56:21 +00:00
|
|
|
Name: "site_id",
|
|
|
|
Label: "family id",
|
|
|
|
Type: base.TypeString,
|
2022-03-09 12:30:56 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "order_by",
|
|
|
|
Label: "order_by",
|
|
|
|
Type: base.TypeSelect,
|
|
|
|
Values: "filename,filesize,lastOpTime",
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "order_direction",
|
|
|
|
Label: "desc",
|
|
|
|
Type: base.TypeSelect,
|
|
|
|
Values: "true,false",
|
|
|
|
Required: true,
|
|
|
|
},
|
2022-04-03 09:56:21 +00:00
|
|
|
{
|
|
|
|
Name: "bool_1",
|
|
|
|
Label: "fast upload",
|
|
|
|
Type: base.TypeBool,
|
|
|
|
},
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) Save(account *model.Account, old *model.Account) error {
|
|
|
|
if account == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if !isFamily(account) && account.RootFolder == "" {
|
|
|
|
account.RootFolder = "-11"
|
2022-04-03 09:56:21 +00:00
|
|
|
account.SiteId = ""
|
|
|
|
}
|
|
|
|
if isFamily(account) && account.RootFolder == "-11" {
|
|
|
|
account.RootFolder = ""
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
state := GetState(account)
|
2022-04-03 09:56:21 +00:00
|
|
|
if !state.IsLogin(account) {
|
2022-03-16 06:22:42 +00:00
|
|
|
if err := state.Login(account); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
2022-03-16 06:22:42 +00:00
|
|
|
|
|
|
|
if isFamily(account) {
|
|
|
|
list, err := driver.getFamilyInfoList(account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for _, l := range list {
|
|
|
|
if account.SiteId == "" {
|
|
|
|
account.SiteId = fmt.Sprint(l.FamilyID)
|
|
|
|
}
|
|
|
|
log.Infof("天翼家庭云 用户名:%s FamilyID %d\n", l.RemarkName, l.FamilyID)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-09 12:30:56 +00:00
|
|
|
account.Status = "work"
|
|
|
|
model.SaveAccount(account)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-03-16 06:22:42 +00:00
|
|
|
func (driver Cloud189) getFamilyInfoList(account *model.Account) ([]FamilyInfoResp, error) {
|
|
|
|
var resp FamilyInfoListResp
|
2022-04-03 09:56:21 +00:00
|
|
|
_, err := GetState(account).Request(http.MethodGet, API_URL+"/family/manage/getFamilyList.action", nil, func(r *resty.Request) {
|
2022-03-16 06:22:42 +00:00
|
|
|
r.SetQueryParams(clientSuffix())
|
|
|
|
r.SetResult(&resp)
|
|
|
|
}, account)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return resp.FamilyInfoResp, nil
|
|
|
|
}
|
|
|
|
|
2022-03-09 12:30:56 +00:00
|
|
|
func (driver Cloud189) File(path string, account *model.Account) (*model.File, error) {
|
|
|
|
path = utils.ParsePath(path)
|
|
|
|
if path == "/" {
|
|
|
|
return &model.File{
|
|
|
|
Id: account.RootFolder,
|
|
|
|
Name: account.Name,
|
|
|
|
Size: 0,
|
|
|
|
Type: conf.FOLDER,
|
|
|
|
Driver: driver.Config().Name,
|
|
|
|
UpdatedAt: account.UpdatedAt,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
dir, name := filepath.Split(path)
|
|
|
|
files, err := driver.Files(dir, account)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
for _, file := range files {
|
|
|
|
if file.Name == name {
|
|
|
|
return &file, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, base.ErrPathNotFound
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) Files(path string, account *model.Account) ([]model.File, error) {
|
|
|
|
path = utils.ParsePath(path)
|
|
|
|
cache, err := base.GetCache(path, account)
|
|
|
|
if err == nil {
|
|
|
|
files, _ := cache.([]model.File)
|
|
|
|
return files, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
file, err := driver.File(path, account)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
fullUrl := API_URL
|
|
|
|
if isFamily(account) {
|
|
|
|
fullUrl += "/family/file"
|
|
|
|
}
|
|
|
|
fullUrl += "/listFiles.action"
|
|
|
|
|
|
|
|
files := make([]model.File, 0)
|
|
|
|
client := GetState(account)
|
|
|
|
for pageNum := 1; ; pageNum++ {
|
|
|
|
var resp Cloud189FilesResp
|
2022-04-03 09:56:21 +00:00
|
|
|
_, err = client.Request(http.MethodGet, fullUrl, nil, func(r *resty.Request) {
|
|
|
|
r.SetQueryParams(clientSuffix()).
|
|
|
|
SetQueryParams(map[string]string{
|
|
|
|
"folderId": file.Id,
|
|
|
|
"fileType": "0",
|
|
|
|
"mediaAttr": "0",
|
|
|
|
"iconOption": "5",
|
|
|
|
"pageNum": fmt.Sprint(pageNum),
|
|
|
|
"pageSize": "130",
|
|
|
|
})
|
2022-03-09 12:30:56 +00:00
|
|
|
if isFamily(account) {
|
|
|
|
r.SetQueryParams(map[string]string{
|
|
|
|
"familyId": account.SiteId,
|
|
|
|
"orderBy": toFamilyOrderBy(account.OrderBy),
|
|
|
|
"descending": account.OrderDirection,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
r.SetQueryParams(map[string]string{
|
|
|
|
"recursive": "0",
|
|
|
|
"orderBy": account.OrderBy,
|
|
|
|
"descending": account.OrderDirection,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
r.SetResult(&resp)
|
|
|
|
}, account)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
// 获取完毕跳出
|
|
|
|
if resp.FileListAO.Count == 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, folder := range resp.FileListAO.FolderList {
|
|
|
|
files = append(files, model.File{
|
|
|
|
Id: fmt.Sprint(folder.ID),
|
|
|
|
Name: folder.Name,
|
|
|
|
Size: 0,
|
|
|
|
Type: conf.FOLDER,
|
|
|
|
Driver: driver.Config().Name,
|
2022-04-06 09:58:57 +00:00
|
|
|
UpdatedAt: MustParseTime(folder.LastOpTime),
|
2022-03-09 12:30:56 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
for _, file := range resp.FileListAO.FileList {
|
|
|
|
files = append(files, model.File{
|
|
|
|
Id: fmt.Sprint(file.ID),
|
|
|
|
Name: file.Name,
|
|
|
|
Size: file.Size,
|
|
|
|
Type: utils.GetFileType(filepath.Ext(file.Name)),
|
|
|
|
Driver: driver.Config().Name,
|
2022-04-06 09:58:57 +00:00
|
|
|
UpdatedAt: MustParseTime(file.LastOpTime),
|
2022-03-09 12:30:56 +00:00
|
|
|
Thumbnail: file.Icon.SmallUrl,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2022-03-09 13:09:21 +00:00
|
|
|
if len(files) > 0 {
|
|
|
|
_ = base.SetCache(path, files, account)
|
|
|
|
}
|
2022-03-09 12:30:56 +00:00
|
|
|
return files, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) Path(path string, account *model.Account) (*model.File, []model.File, error) {
|
|
|
|
path = utils.ParsePath(path)
|
|
|
|
log.Debugf("189PC path: %s", path)
|
|
|
|
file, err := driver.File(path, account)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
if !file.IsDir() {
|
|
|
|
return file, nil, nil
|
|
|
|
}
|
|
|
|
files, err := driver.Files(path, account)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
return nil, files, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) Link(args base.Args, account *model.Account) (*base.Link, error) {
|
|
|
|
file, err := driver.File(utils.ParsePath(args.Path), account)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if file.Type == conf.FOLDER {
|
|
|
|
return nil, base.ErrNotFile
|
|
|
|
}
|
|
|
|
|
|
|
|
fullUrl := API_URL
|
|
|
|
if isFamily(account) {
|
|
|
|
fullUrl += "/family/file"
|
|
|
|
}
|
|
|
|
fullUrl += "/getFileDownloadUrl.action"
|
|
|
|
|
|
|
|
var downloadUrl struct {
|
|
|
|
URL string `json:"fileDownloadUrl"`
|
|
|
|
}
|
2022-04-03 09:56:21 +00:00
|
|
|
_, err = GetState(account).Request(http.MethodGet, fullUrl, nil, func(r *resty.Request) {
|
2022-03-09 12:30:56 +00:00
|
|
|
r.SetQueryParams(clientSuffix()).SetQueryParam("fileId", file.Id)
|
|
|
|
if isFamily(account) {
|
|
|
|
r.SetQueryParams(map[string]string{
|
|
|
|
"familyId": account.SiteId,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
r.SetQueryParams(map[string]string{
|
|
|
|
"dt": "3",
|
|
|
|
"flag": "1",
|
|
|
|
})
|
|
|
|
}
|
|
|
|
r.SetResult(&downloadUrl)
|
|
|
|
}, account)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-03-09 14:48:15 +00:00
|
|
|
return &base.Link{
|
|
|
|
Headers: []base.Header{
|
|
|
|
{Name: "User-Agent", Value: base.UserAgent},
|
|
|
|
},
|
|
|
|
Url: strings.ReplaceAll(downloadUrl.URL, "&", "&"),
|
|
|
|
}, nil
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) Preview(path string, account *model.Account) (interface{}, error) {
|
|
|
|
return nil, base.ErrNotSupport
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) MakeDir(path string, account *model.Account) error {
|
|
|
|
dir, name := filepath.Split(path)
|
|
|
|
parentFile, err := driver.File(dir, account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if !parentFile.IsDir() {
|
|
|
|
return base.ErrNotFolder
|
|
|
|
}
|
|
|
|
|
|
|
|
fullUrl := API_URL
|
|
|
|
if isFamily(account) {
|
|
|
|
fullUrl += "/family/file"
|
|
|
|
}
|
|
|
|
fullUrl += "/createFolder.action"
|
|
|
|
|
2022-04-03 09:56:21 +00:00
|
|
|
_, err = GetState(account).Request(http.MethodPost, fullUrl, nil, func(r *resty.Request) {
|
2022-03-09 12:30:56 +00:00
|
|
|
r.SetQueryParams(clientSuffix()).SetQueryParams(map[string]string{
|
|
|
|
"folderName": name,
|
|
|
|
"relativePath": "",
|
|
|
|
})
|
|
|
|
if isFamily(account) {
|
|
|
|
r.SetQueryParams(map[string]string{
|
|
|
|
"familyId": account.SiteId,
|
|
|
|
"parentId": parentFile.Id,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
r.SetQueryParams(map[string]string{
|
|
|
|
"parentFolderId": parentFile.Id,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}, account)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) Move(src string, dst string, account *model.Account) error {
|
|
|
|
srcFile, err := driver.File(src, account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
dstDirFile, err := driver.File(filepath.Dir(dst), account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-04-03 09:56:21 +00:00
|
|
|
_, err = GetState(account).Request(http.MethodPost, API_URL+"/batch/createBatchTask.action", nil, func(r *resty.Request) {
|
2022-03-09 12:30:56 +00:00
|
|
|
r.SetFormData(clientSuffix()).SetFormData(map[string]string{
|
|
|
|
"type": "MOVE",
|
2022-03-16 06:22:42 +00:00
|
|
|
"taskInfos": string(MustToBytes(utils.Json.Marshal(
|
2022-03-09 12:30:56 +00:00
|
|
|
[]*BatchTaskInfo{
|
|
|
|
{
|
|
|
|
FileId: srcFile.Id,
|
|
|
|
FileName: srcFile.Name,
|
|
|
|
IsFolder: BoolToNumber(srcFile.IsDir()),
|
|
|
|
},
|
|
|
|
}))),
|
|
|
|
"targetFolderId": dstDirFile.Id,
|
|
|
|
})
|
|
|
|
if isFamily(account) {
|
|
|
|
r.SetFormData(map[string]string{
|
|
|
|
"familyId": account.SiteId,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}, account)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
func (driver Cloud189) Move(src string, dst string, account *model.Account) error {
|
|
|
|
srcFile, err := driver.File(src, account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
dstDirFile, err := driver.File(filepath.Dir(dst), account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var queryParam map[string]string
|
|
|
|
fullUrl := API_URL
|
2022-04-03 09:56:21 +00:00
|
|
|
method := http.MethodPost
|
2022-03-09 12:30:56 +00:00
|
|
|
if isFamily(account) {
|
|
|
|
fullUrl += "/family/file"
|
2022-04-03 09:56:21 +00:00
|
|
|
method = http.MethodGet
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
|
|
|
if srcFile.IsDir() {
|
|
|
|
fullUrl += "/moveFolder.action"
|
|
|
|
queryParam = map[string]string{
|
|
|
|
"folderId": srcFile.Id,
|
|
|
|
"destFolderName": srcFile.Name,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
fullUrl += "/moveFile.action"
|
|
|
|
queryParam = map[string]string{
|
|
|
|
"fileId": srcFile.Id,
|
|
|
|
"destFileName": srcFile.Name,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = GetState(account).Request(method, fullUrl, nil, func(r *resty.Request) {
|
|
|
|
r.SetQueryParams(queryParam).SetQueryParams(clientSuffix())
|
|
|
|
if isFamily(account) {
|
|
|
|
r.SetQueryParams(map[string]string{
|
|
|
|
"familyId": account.SiteId,
|
|
|
|
"destParentId": dstDirFile.Id,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
r.SetQueryParam("destParentFolderId", dstDirFile.Id)
|
|
|
|
}
|
|
|
|
}, account)
|
|
|
|
return err
|
|
|
|
}*/
|
|
|
|
|
|
|
|
func (driver Cloud189) Rename(src string, dst string, account *model.Account) error {
|
|
|
|
srcFile, err := driver.File(src, account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var queryParam map[string]string
|
|
|
|
fullUrl := API_URL
|
2022-04-03 09:56:21 +00:00
|
|
|
method := http.MethodPost
|
2022-03-09 12:30:56 +00:00
|
|
|
if isFamily(account) {
|
|
|
|
fullUrl += "/family/file"
|
2022-04-03 09:56:21 +00:00
|
|
|
method = http.MethodGet
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
|
|
|
if srcFile.IsDir() {
|
|
|
|
fullUrl += "/renameFolder.action"
|
|
|
|
queryParam = map[string]string{
|
|
|
|
"folderId": srcFile.Id,
|
|
|
|
"destFolderName": filepath.Base(dst),
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
fullUrl += "/renameFile.action"
|
|
|
|
queryParam = map[string]string{
|
|
|
|
"fileId": srcFile.Id,
|
|
|
|
"destFileName": filepath.Base(dst),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = GetState(account).Request(method, fullUrl, nil, func(r *resty.Request) {
|
|
|
|
r.SetQueryParams(queryParam).SetQueryParams(clientSuffix())
|
|
|
|
if isFamily(account) {
|
|
|
|
r.SetQueryParam("familyId", account.SiteId)
|
|
|
|
}
|
|
|
|
}, account)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) Copy(src string, dst string, account *model.Account) error {
|
|
|
|
srcFile, err := driver.File(src, account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
dstDirFile, err := driver.File(filepath.Dir(dst), account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-04-03 09:56:21 +00:00
|
|
|
_, err = GetState(account).Request(http.MethodPost, API_URL+"/batch/createBatchTask.action", nil, func(r *resty.Request) {
|
2022-03-09 12:30:56 +00:00
|
|
|
r.SetFormData(clientSuffix()).SetFormData(map[string]string{
|
|
|
|
"type": "COPY",
|
2022-03-16 06:22:42 +00:00
|
|
|
"taskInfos": string(MustToBytes(utils.Json.Marshal(
|
2022-03-09 12:30:56 +00:00
|
|
|
[]*BatchTaskInfo{
|
|
|
|
{
|
|
|
|
FileId: srcFile.Id,
|
|
|
|
FileName: srcFile.Name,
|
2022-03-09 14:48:15 +00:00
|
|
|
IsFolder: BoolToNumber(srcFile.IsDir()),
|
2022-03-09 12:30:56 +00:00
|
|
|
},
|
|
|
|
}))),
|
|
|
|
"targetFolderId": dstDirFile.Id,
|
|
|
|
"targetFileName": filepath.Base(dst),
|
|
|
|
})
|
|
|
|
if isFamily(account) {
|
|
|
|
r.SetFormData(map[string]string{
|
|
|
|
"familyId": account.SiteId,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}, account)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) Delete(path string, account *model.Account) error {
|
|
|
|
path = utils.ParsePath(path)
|
|
|
|
srcFile, err := driver.File(path, account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-04-03 09:56:21 +00:00
|
|
|
_, err = GetState(account).Request(http.MethodPost, API_URL+"/batch/createBatchTask.action", nil, func(r *resty.Request) {
|
2022-03-09 12:30:56 +00:00
|
|
|
r.SetFormData(clientSuffix()).SetFormData(map[string]string{
|
|
|
|
"type": "DELETE",
|
2022-03-16 06:22:42 +00:00
|
|
|
"taskInfos": string(MustToBytes(utils.Json.Marshal(
|
2022-03-09 12:30:56 +00:00
|
|
|
[]*BatchTaskInfo{
|
|
|
|
{
|
|
|
|
FileId: srcFile.Id,
|
|
|
|
FileName: srcFile.Name,
|
|
|
|
IsFolder: BoolToNumber(srcFile.IsDir()),
|
|
|
|
},
|
|
|
|
}))),
|
|
|
|
})
|
|
|
|
|
|
|
|
if isFamily(account) {
|
|
|
|
r.SetFormData(map[string]string{
|
|
|
|
"familyId": account.SiteId,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}, account)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) Upload(file *model.FileStream, account *model.Account) error {
|
|
|
|
if file == nil {
|
|
|
|
return base.ErrEmptyFile
|
|
|
|
}
|
|
|
|
|
|
|
|
parentFile, err := driver.File(file.ParentPath, account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if !parentFile.IsDir() {
|
|
|
|
return base.ErrNotFolder
|
|
|
|
}
|
|
|
|
|
2022-04-03 09:56:21 +00:00
|
|
|
if account.Bool1 {
|
|
|
|
return driver.FastUpload(file, parentFile, account)
|
|
|
|
}
|
|
|
|
return driver.CommonUpload(file, parentFile, account)
|
|
|
|
/*
|
|
|
|
if isFamily(account) {
|
|
|
|
return driver.uploadFamily(file, parentFile, account)
|
|
|
|
}
|
|
|
|
return driver.uploadPerson(file, parentFile, account)
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) CommonUpload(file *model.FileStream, parentFile *model.File, account *model.Account) error {
|
|
|
|
// 初始化上传
|
|
|
|
state := GetState(account)
|
|
|
|
const DEFAULT int64 = 10485760
|
|
|
|
count := int(math.Ceil(float64(file.Size) / float64(DEFAULT)))
|
|
|
|
|
|
|
|
params := Params{
|
|
|
|
"parentFolderId": parentFile.Id,
|
|
|
|
"fileName": url.PathEscape(file.Name),
|
|
|
|
"fileSize": fmt.Sprint(file.Size),
|
|
|
|
"sliceSize": fmt.Sprint(DEFAULT),
|
|
|
|
"lazyCheck": "1",
|
|
|
|
}
|
|
|
|
|
|
|
|
fullUrl := UPLOAD_URL
|
2022-03-09 12:30:56 +00:00
|
|
|
if isFamily(account) {
|
2022-04-03 09:56:21 +00:00
|
|
|
params.Set("familyId", account.SiteId)
|
|
|
|
fullUrl += "/family"
|
|
|
|
} else {
|
|
|
|
//params.Set("extend", `{"opScene":"1","relativepath":"","rootfolderid":""}`)
|
|
|
|
fullUrl += "/person"
|
|
|
|
}
|
|
|
|
|
|
|
|
var initMultiUpload InitMultiUploadResp
|
|
|
|
_, err := state.Request(http.MethodGet, fullUrl+"/initMultiUpload", params, func(r *resty.Request) { r.SetQueryParams(clientSuffix()).SetResult(&initMultiUpload) }, account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
2022-04-03 09:56:21 +00:00
|
|
|
|
|
|
|
fileMd5 := md5.New()
|
|
|
|
silceMd5 := md5.New()
|
|
|
|
silceMd5Hexs := make([]string, 0, count)
|
|
|
|
byteData := bytes.NewBuffer(make([]byte, DEFAULT))
|
|
|
|
for i := 1; i <= count; i++ {
|
|
|
|
byteData.Reset()
|
|
|
|
silceMd5.Reset()
|
|
|
|
if n, err := io.CopyN(io.MultiWriter(fileMd5, silceMd5, byteData), file, DEFAULT); err != io.EOF && n == 0 {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
md5Bytes := silceMd5.Sum(nil)
|
|
|
|
silceMd5Hexs = append(silceMd5Hexs, strings.ToUpper(hex.EncodeToString(md5Bytes)))
|
|
|
|
silceMd5Base64 := base64.StdEncoding.EncodeToString(md5Bytes)
|
|
|
|
|
|
|
|
var uploadUrl UploadUrlsResp
|
|
|
|
_, err = state.Request(http.MethodGet, fullUrl+"/getMultiUploadUrls",
|
|
|
|
Params{"partInfo": fmt.Sprintf("%d-%s", i, silceMd5Base64), "uploadFileId": initMultiUpload.Data.UploadFileID},
|
|
|
|
func(r *resty.Request) { r.SetQueryParams(clientSuffix()).SetResult(&uploadUrl) },
|
|
|
|
account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
uploadData := uploadUrl.UploadUrls[fmt.Sprint("partNumber_", i)]
|
|
|
|
req, _ := http.NewRequest(http.MethodPut, uploadData.RequestURL, byteData)
|
|
|
|
for k, v := range ParseHttpHeader(uploadData.RequestHeader) {
|
|
|
|
req.Header.Set(k, v)
|
|
|
|
}
|
|
|
|
for k, v := range clientSuffix() {
|
|
|
|
req.URL.RawQuery += fmt.Sprintf("&%s=%s", k, v)
|
|
|
|
}
|
|
|
|
r, err := base.HttpClient.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if r.StatusCode != http.StatusOK {
|
|
|
|
data, _ := io.ReadAll(r.Body)
|
|
|
|
return fmt.Errorf(string(data))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fileMd5Hex := strings.ToUpper(hex.EncodeToString(fileMd5.Sum(nil)))
|
|
|
|
sliceMd5Hex := fileMd5Hex
|
|
|
|
if int64(file.Size) > DEFAULT {
|
|
|
|
sliceMd5Hex = strings.ToUpper(utils.GetMD5Encode(strings.Join(silceMd5Hexs, "\n")))
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = state.Request(http.MethodGet, fullUrl+"/commitMultiUploadFile",
|
|
|
|
Params{
|
|
|
|
"uploadFileId": initMultiUpload.Data.UploadFileID,
|
|
|
|
"fileMd5": fileMd5Hex,
|
|
|
|
"sliceMd5": sliceMd5Hex,
|
|
|
|
"lazyCheck": "1",
|
|
|
|
"isLog": "0",
|
|
|
|
"opertype": "3",
|
|
|
|
},
|
|
|
|
func(r *resty.Request) { r.SetQueryParams(clientSuffix()) }, account)
|
|
|
|
return err
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
|
|
|
|
2022-04-03 09:56:21 +00:00
|
|
|
func (driver Cloud189) FastUpload(file *model.FileStream, parentFile *model.File, account *model.Account) error {
|
|
|
|
tempFile, err := ioutil.TempFile(conf.Conf.TempDir, "file-*")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer tempFile.Close()
|
|
|
|
defer os.Remove(tempFile.Name())
|
|
|
|
|
|
|
|
// 初始化上传
|
|
|
|
state := GetState(account)
|
|
|
|
|
|
|
|
const DEFAULT int64 = 10485760
|
|
|
|
count := int(math.Ceil(float64(file.Size) / float64(DEFAULT)))
|
|
|
|
|
|
|
|
// 优先计算所需信息
|
|
|
|
fileMd5 := md5.New()
|
|
|
|
silceMd5 := md5.New()
|
|
|
|
silceMd5Hexs := make([]string, 0, count)
|
|
|
|
silceMd5Base64s := make([]string, 0, count)
|
|
|
|
for i := 1; i <= count; i++ {
|
|
|
|
silceMd5.Reset()
|
|
|
|
if n, err := io.CopyN(io.MultiWriter(fileMd5, silceMd5, tempFile), file, DEFAULT); err != nil && n == 0 {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
md5Byte := silceMd5.Sum(nil)
|
|
|
|
silceMd5Hexs = append(silceMd5Hexs, strings.ToUpper(hex.EncodeToString(md5Byte)))
|
|
|
|
silceMd5Base64s = append(silceMd5Base64s, fmt.Sprint(i, "-", base64.StdEncoding.EncodeToString(md5Byte)))
|
|
|
|
}
|
|
|
|
fileMd5Hex := strings.ToUpper(hex.EncodeToString(fileMd5.Sum(nil)))
|
|
|
|
sliceMd5Hex := fileMd5Hex
|
|
|
|
if int64(file.Size) > DEFAULT {
|
|
|
|
sliceMd5Hex = strings.ToUpper(utils.GetMD5Encode(strings.Join(silceMd5Hexs, "\n")))
|
|
|
|
}
|
|
|
|
|
|
|
|
params := Params{
|
|
|
|
"parentFolderId": parentFile.Id,
|
|
|
|
"fileName": url.PathEscape(file.Name),
|
|
|
|
"fileSize": fmt.Sprint(file.Size),
|
|
|
|
"fileMd5": fileMd5Hex,
|
|
|
|
"sliceSize": fmt.Sprint(DEFAULT),
|
|
|
|
"sliceMd5": sliceMd5Hex,
|
|
|
|
}
|
|
|
|
|
|
|
|
fullUrl := UPLOAD_URL
|
|
|
|
if isFamily(account) {
|
|
|
|
params.Set("familyId", account.SiteId)
|
|
|
|
fullUrl += "/family"
|
|
|
|
} else {
|
|
|
|
//params.Set("extend", `{"opScene":"1","relativepath":"","rootfolderid":""}`)
|
|
|
|
fullUrl += "/person"
|
|
|
|
}
|
|
|
|
|
|
|
|
var uploadInfo InitMultiUploadResp
|
|
|
|
_, err = state.Request(http.MethodGet, fullUrl+"/initMultiUpload", params, func(r *resty.Request) { r.SetQueryParams(clientSuffix()).SetResult(&uploadInfo) }, account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if uploadInfo.Data.FileDataExists != 1 {
|
|
|
|
var uploadUrls UploadUrlsResp
|
|
|
|
_, err := state.Request(http.MethodGet, fullUrl+"/getMultiUploadUrls",
|
|
|
|
Params{
|
|
|
|
"uploadFileId": uploadInfo.Data.UploadFileID,
|
|
|
|
"partInfo": strings.Join(silceMd5Base64s, ","),
|
|
|
|
},
|
|
|
|
func(r *resty.Request) { r.SetQueryParams(clientSuffix()).SetResult(&uploadUrls) },
|
|
|
|
account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := 1; i <= count; i++ {
|
|
|
|
uploadData := uploadUrls.UploadUrls[fmt.Sprint("partNumber_", i)]
|
|
|
|
req, _ := http.NewRequest(http.MethodPut, uploadData.RequestURL, io.NewSectionReader(tempFile, int64(i-1)*DEFAULT, DEFAULT))
|
|
|
|
for k, v := range ParseHttpHeader(uploadData.RequestHeader) {
|
|
|
|
req.Header.Set(k, v)
|
|
|
|
}
|
|
|
|
for k, v := range clientSuffix() {
|
|
|
|
req.URL.RawQuery += fmt.Sprintf("&%s=%s", k, v)
|
|
|
|
}
|
|
|
|
r, err := base.HttpClient.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if r.StatusCode != http.StatusOK {
|
|
|
|
data, _ := io.ReadAll(r.Body)
|
|
|
|
return fmt.Errorf(string(data))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = state.Request(http.MethodGet, fullUrl+"/commitMultiUploadFile",
|
|
|
|
Params{
|
|
|
|
"uploadFileId": uploadInfo.Data.UploadFileID,
|
|
|
|
"isLog": "0",
|
|
|
|
"opertype": "3",
|
|
|
|
},
|
|
|
|
func(r *resty.Request) { r.SetQueryParams(clientSuffix()) },
|
|
|
|
account)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2022-03-09 12:30:56 +00:00
|
|
|
func (driver Cloud189) uploadFamily(file *model.FileStream, parentFile *model.File, account *model.Account) error {
|
|
|
|
tempFile, err := ioutil.TempFile(conf.Conf.TempDir, "file-*")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer tempFile.Close()
|
|
|
|
defer os.Remove(tempFile.Name())
|
|
|
|
|
|
|
|
fileMd5 := md5.New()
|
|
|
|
if _, err = io.Copy(io.MultiWriter(fileMd5, tempFile), file); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
client := GetState(account)
|
|
|
|
var createUpload CreateUploadFileResult
|
2022-04-03 09:56:21 +00:00
|
|
|
_, err = client.Request(http.MethodGet, API_URL+"/family/file/createFamilyFile.action", nil, func(r *resty.Request) {
|
2022-03-09 12:30:56 +00:00
|
|
|
r.SetQueryParams(map[string]string{
|
|
|
|
"fileMd5": hex.EncodeToString(fileMd5.Sum(nil)),
|
|
|
|
"fileName": file.Name,
|
2022-03-09 14:48:15 +00:00
|
|
|
"familyId": account.SiteId,
|
2022-03-09 12:30:56 +00:00
|
|
|
"parentId": parentFile.Id,
|
|
|
|
"resumePolicy": "1",
|
|
|
|
"fileSize": fmt.Sprint(file.Size),
|
|
|
|
})
|
|
|
|
r.SetQueryParams(clientSuffix())
|
|
|
|
r.SetResult(&createUpload)
|
|
|
|
}, account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if createUpload.FileDataExists != 1 {
|
2022-03-16 06:22:42 +00:00
|
|
|
if createUpload.UploadFileId, err = driver.uploadFileData(file, tempFile, createUpload, account); err != nil {
|
2022-03-09 12:30:56 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-03 09:56:21 +00:00
|
|
|
_, err = client.Request(http.MethodGet, createUpload.FileCommitUrl, nil, func(r *resty.Request) {
|
2022-03-09 12:30:56 +00:00
|
|
|
r.SetQueryParams(clientSuffix())
|
|
|
|
r.SetHeaders(map[string]string{
|
2022-03-09 14:48:15 +00:00
|
|
|
"FamilyId": account.SiteId,
|
2022-03-09 12:30:56 +00:00
|
|
|
"uploadFileId": fmt.Sprint(createUpload.UploadFileId),
|
|
|
|
"ResumePolicy": "1",
|
|
|
|
})
|
|
|
|
}, account)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) uploadPerson(file *model.FileStream, parentFile *model.File, account *model.Account) error {
|
|
|
|
tempFile, err := ioutil.TempFile(conf.Conf.TempDir, "file-*")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer tempFile.Close()
|
|
|
|
defer os.Remove(tempFile.Name())
|
|
|
|
|
|
|
|
fileMd5 := md5.New()
|
|
|
|
if _, err = io.Copy(io.MultiWriter(fileMd5, tempFile), file); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
client := GetState(account)
|
|
|
|
var createUpload CreateUploadFileResult
|
2022-04-03 09:56:21 +00:00
|
|
|
_, err = client.Request(http.MethodPost, API_URL+"/createUploadFile.action", nil, func(r *resty.Request) {
|
2022-03-09 12:30:56 +00:00
|
|
|
r.SetQueryParams(clientSuffix())
|
|
|
|
r.SetFormData(clientSuffix()).SetFormData(map[string]string{
|
|
|
|
"parentFolderId": parentFile.Id,
|
|
|
|
"baseFileId": "",
|
|
|
|
"fileName": file.Name,
|
|
|
|
"size": fmt.Sprint(file.Size),
|
|
|
|
"md5": hex.EncodeToString(fileMd5.Sum(nil)),
|
|
|
|
// "lastWrite": param.LastWrite,
|
|
|
|
// "localPath": strings.ReplaceAll(file.ParentPath, "\\", "/"),
|
|
|
|
"opertype": "1",
|
|
|
|
"flag": "1",
|
|
|
|
"resumePolicy": "1",
|
|
|
|
"isLog": "0",
|
|
|
|
"fileExt": "",
|
|
|
|
})
|
|
|
|
r.SetResult(&createUpload)
|
|
|
|
}, account)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if createUpload.FileDataExists != 1 {
|
2022-03-16 06:22:42 +00:00
|
|
|
if createUpload.UploadFileId, err = driver.uploadFileData(file, tempFile, createUpload, account); err != nil {
|
2022-03-09 12:30:56 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-03 09:56:21 +00:00
|
|
|
_, err = client.Request(http.MethodPost, createUpload.FileCommitUrl, nil, func(r *resty.Request) {
|
2022-03-09 12:30:56 +00:00
|
|
|
r.SetQueryParams(clientSuffix())
|
|
|
|
r.SetFormData(map[string]string{
|
|
|
|
"uploadFileId": fmt.Sprint(createUpload.UploadFileId),
|
2022-03-23 10:51:07 +00:00
|
|
|
"opertype": "5", //5 覆盖 1 重命名
|
2022-03-09 12:30:56 +00:00
|
|
|
"ResumePolicy": "1",
|
|
|
|
"isLog": "0",
|
|
|
|
})
|
|
|
|
}, account)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-03-16 06:22:42 +00:00
|
|
|
func (driver Cloud189) uploadFileData(file *model.FileStream, tempFile *os.File, createUpload CreateUploadFileResult, account *model.Account) (int64, error) {
|
|
|
|
uploadFileState, err := driver.getUploadFileState(createUpload.UploadFileId, account)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
2022-03-09 12:30:56 +00:00
|
|
|
|
2022-03-16 06:22:42 +00:00
|
|
|
if uploadFileState.FileDataExists == 1 || uploadFileState.DataSize == int64(file.Size) {
|
|
|
|
return uploadFileState.UploadFileId, nil
|
|
|
|
}
|
2022-03-09 12:30:56 +00:00
|
|
|
|
2022-03-16 06:22:42 +00:00
|
|
|
if _, err = tempFile.Seek(uploadFileState.DataSize, io.SeekStart); err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
2022-03-09 12:30:56 +00:00
|
|
|
|
2022-03-16 06:22:42 +00:00
|
|
|
_, err = GetState(account).Request("PUT", uploadFileState.FileUploadUrl, nil, func(r *resty.Request) {
|
|
|
|
r.SetQueryParams(clientSuffix())
|
|
|
|
r.SetHeaders(map[string]string{
|
|
|
|
"Content-Type": "application/octet-stream",
|
|
|
|
"ResumePolicy": "1",
|
|
|
|
"Edrive-UploadFileRange": fmt.Sprintf("bytes=%d-%d", uploadFileState.DataSize, file.Size),
|
|
|
|
"Expect": "100-continue",
|
|
|
|
})
|
|
|
|
if isFamily(account) {
|
2022-03-09 12:30:56 +00:00
|
|
|
r.SetHeaders(map[string]string{
|
2022-03-16 06:22:42 +00:00
|
|
|
"familyId": account.SiteId,
|
|
|
|
"UploadFileId": fmt.Sprint(uploadFileState.UploadFileId),
|
2022-03-09 12:30:56 +00:00
|
|
|
})
|
2022-03-16 06:22:42 +00:00
|
|
|
} else {
|
|
|
|
r.SetHeader("Edrive-UploadFileId", fmt.Sprint(uploadFileState.UploadFileId))
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
2022-03-16 06:22:42 +00:00
|
|
|
r.SetBody(tempFile)
|
|
|
|
}, account)
|
|
|
|
return uploadFileState.UploadFileId, err
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (driver Cloud189) getUploadFileState(uploadFileId int64, account *model.Account) (*UploadFileStatusResult, error) {
|
|
|
|
fullUrl := API_URL
|
|
|
|
if isFamily(account) {
|
|
|
|
fullUrl += "/family/file/getFamilyFileStatus.action"
|
|
|
|
} else {
|
|
|
|
fullUrl += "/getUploadFileStatus.action"
|
|
|
|
}
|
|
|
|
var uploadFileState UploadFileStatusResult
|
2022-04-03 09:56:21 +00:00
|
|
|
_, err := GetState(account).Request(http.MethodGet, fullUrl, nil, func(r *resty.Request) {
|
2022-03-09 12:30:56 +00:00
|
|
|
r.SetQueryParams(clientSuffix())
|
|
|
|
r.SetQueryParams(map[string]string{
|
|
|
|
"uploadFileId": fmt.Sprint(uploadFileId),
|
|
|
|
"resumePolicy": "1",
|
|
|
|
})
|
|
|
|
if isFamily(account) {
|
2022-03-09 14:48:15 +00:00
|
|
|
r.SetQueryParam("familyId", account.SiteId)
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
|
|
|
r.SetResult(&uploadFileState)
|
|
|
|
}, account)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &uploadFileState, nil
|
2022-04-03 09:56:21 +00:00
|
|
|
}*/
|
2022-03-09 12:30:56 +00:00
|
|
|
|
|
|
|
var _ base.Driver = (*Cloud189)(nil)
|