mirror of
https://github.com/XZB-1248/Spark
synced 2025-10-05 16:16:49 +08:00
177 lines
3.5 KiB
Go
177 lines
3.5 KiB
Go
package file
|
|
|
|
import (
|
|
"Spark/client/config"
|
|
"errors"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"strconv"
|
|
|
|
"github.com/imroc/req/v3"
|
|
)
|
|
|
|
type File struct {
|
|
Name string `json:"name"`
|
|
Size uint64 `json:"size"`
|
|
Time int64 `json:"time"`
|
|
Type int `json:"type"` // 0: file, 1: folder, 2: volume
|
|
}
|
|
|
|
// listFiles returns files and directories find in path.
|
|
func listFiles(path string) ([]File, error) {
|
|
result := make([]File, 0)
|
|
files, err := ioutil.ReadDir(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for i := 0; i < len(files); i++ {
|
|
itemType := 0
|
|
if files[i].IsDir() {
|
|
itemType = 1
|
|
}
|
|
result = append(result, File{
|
|
Name: files[i].Name(),
|
|
Size: uint64(files[i].Size()),
|
|
Time: files[i].ModTime().Unix(),
|
|
Type: itemType,
|
|
})
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// FetchFile saves file from bridge to local.
|
|
// Save body as temp file and when done, rename it to file.
|
|
func FetchFile(dir, file, bridge string) error {
|
|
url := config.GetBaseURL(false) + `/api/bridge/pull`
|
|
client := req.C().DisableAutoReadResponse()
|
|
resp, err := client.R().SetQueryParam(`bridge`, bridge).Get(url)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
// If dest file exists, write to temp file first.
|
|
dest := path.Join(dir, file)
|
|
tmpFile := dest
|
|
destExists := false
|
|
if _, err := os.Stat(dest); !os.IsNotExist(err) {
|
|
tmpFile = getTempFileName(dir, file)
|
|
destExists = true
|
|
}
|
|
|
|
fh, err := os.Create(tmpFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for {
|
|
buf := make([]byte, 1024)
|
|
n, err := resp.Body.Read(buf)
|
|
if err != nil && err != io.EOF {
|
|
fh.Truncate(0)
|
|
fh.Close()
|
|
os.Remove(tmpFile)
|
|
return err
|
|
}
|
|
if n == 0 {
|
|
break
|
|
}
|
|
_, err = fh.Write(buf[:n])
|
|
if err != nil {
|
|
fh.Truncate(0)
|
|
fh.Close()
|
|
os.Remove(tmpFile)
|
|
return err
|
|
}
|
|
fh.Sync()
|
|
}
|
|
fh.Close()
|
|
|
|
// Delete old file if exists.
|
|
// Then rename temp file to file.
|
|
if destExists {
|
|
os.Remove(dest)
|
|
err = os.Rename(tmpFile, dest)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func RemoveFile(path string) error {
|
|
if path == `\` || path == `/` || len(path) == 0 {
|
|
return errors.New(`${i18n|fileOrDirNotExist}`)
|
|
}
|
|
err := os.RemoveAll(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func UploadFile(path, bridge string, start, end int64) error {
|
|
file, err := os.Open(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
reader, writer := io.Pipe()
|
|
defer file.Close()
|
|
uploadReq := req.R()
|
|
stat, err := file.Stat()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
size := stat.Size()
|
|
headers := map[string]string{
|
|
`FileName`: stat.Name(),
|
|
`FileSize`: strconv.FormatInt(size, 10),
|
|
}
|
|
if size < end {
|
|
return errors.New(`${i18n|invalidFileSize}`)
|
|
}
|
|
if end == 0 {
|
|
uploadReq.RawRequest.ContentLength = size - start
|
|
} else {
|
|
uploadReq.RawRequest.ContentLength = end - start
|
|
}
|
|
shouldRead := uploadReq.RawRequest.ContentLength
|
|
file.Seek(start, 0)
|
|
go func() {
|
|
for {
|
|
bufSize := int64(2 << 14)
|
|
if shouldRead < bufSize {
|
|
bufSize = shouldRead
|
|
}
|
|
buffer := make([]byte, bufSize) // 32768
|
|
n, err := file.Read(buffer)
|
|
buffer = buffer[:n]
|
|
shouldRead -= int64(n)
|
|
writer.Write(buffer)
|
|
if n == 0 || shouldRead == 0 || err != nil {
|
|
break
|
|
}
|
|
}
|
|
writer.Close()
|
|
}()
|
|
url := config.GetBaseURL(false) + `/api/bridge/push`
|
|
_, err = uploadReq.
|
|
SetBody(reader).
|
|
SetHeaders(headers).
|
|
SetQueryParam(`bridge`, bridge).
|
|
Send(`PUT`, url)
|
|
reader.Close()
|
|
return err
|
|
}
|
|
|
|
func getTempFileName(dir, file string) string {
|
|
exists := true
|
|
tempFile := ``
|
|
for i := 0; exists; i++ {
|
|
tempFile = path.Join(dir, file+`.tmp.`+strconv.Itoa(i))
|
|
_, err := os.Stat(tempFile)
|
|
if os.IsNotExist(err) {
|
|
exists = false
|
|
}
|
|
}
|
|
return tempFile
|
|
}
|