mirror of
https://github.com/tickstep/aliyunpan.git
synced 2025-01-23 22:42:15 +08:00
214 lines
5.0 KiB
Go
214 lines
5.0 KiB
Go
// Copyright (c) 2020 tickstep & chenall
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
package panupload
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/tickstep/aliyunpan/internal/config"
|
|
"github.com/tickstep/aliyunpan/internal/file/uploader"
|
|
"github.com/tickstep/aliyunpan/internal/localfile"
|
|
"github.com/tickstep/library-go/converter"
|
|
"github.com/tickstep/library-go/jsonhelper"
|
|
)
|
|
|
|
type (
|
|
// Uploading 未完成上传的信息
|
|
Uploading struct {
|
|
*localfile.LocalFileMeta
|
|
State *uploader.InstanceState `json:"state"`
|
|
}
|
|
|
|
// UploadingDatabase 未完成上传的数据库
|
|
UploadingDatabase struct {
|
|
UploadingList []*Uploading `json:"upload_state"`
|
|
Timestamp int64 `json:"timestamp"`
|
|
|
|
dataFile *os.File
|
|
}
|
|
)
|
|
|
|
// NewUploadingDatabase 初始化未完成上传的数据库, 从库中读取内容
|
|
func NewUploadingDatabase() (ud *UploadingDatabase, err error) {
|
|
file, err := os.OpenFile(filepath.Join(config.GetConfigDir(), UploadingFileName), os.O_CREATE|os.O_RDWR, 0777)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ud = &UploadingDatabase{
|
|
dataFile: file,
|
|
}
|
|
info, err := file.Stat()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if info.Size() <= 0 {
|
|
return ud, nil
|
|
}
|
|
|
|
err = jsonhelper.UnmarshalData(file, ud)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return ud, nil
|
|
}
|
|
|
|
// Save 保存内容
|
|
func (ud *UploadingDatabase) Save() error {
|
|
if ud.dataFile == nil {
|
|
return errors.New("dataFile is nil")
|
|
}
|
|
|
|
ud.Timestamp = time.Now().Unix()
|
|
|
|
var (
|
|
builder = &strings.Builder{}
|
|
err = jsonhelper.MarshalData(builder, ud)
|
|
)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
err = ud.dataFile.Truncate(int64(builder.Len()))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
str := builder.String()
|
|
_, err = ud.dataFile.WriteAt(converter.ToBytes(str), 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// UpdateUploading 更新正在上传
|
|
func (ud *UploadingDatabase) UpdateUploading(meta *localfile.LocalFileMeta, state *uploader.InstanceState) {
|
|
if meta == nil {
|
|
return
|
|
}
|
|
|
|
meta.CompleteAbsPath()
|
|
for k, uploading := range ud.UploadingList {
|
|
if uploading.LocalFileMeta == nil {
|
|
continue
|
|
}
|
|
if uploading.LocalFileMeta.EqualLengthMD5(meta) || uploading.LocalFileMeta.Path.LogicPath == meta.Path.LogicPath {
|
|
ud.UploadingList[k].State = state
|
|
return
|
|
}
|
|
}
|
|
|
|
ud.UploadingList = append(ud.UploadingList, &Uploading{
|
|
LocalFileMeta: meta,
|
|
State: state,
|
|
})
|
|
}
|
|
|
|
func (ud *UploadingDatabase) deleteIndex(k int) {
|
|
ud.UploadingList = append(ud.UploadingList[:k], ud.UploadingList[k+1:]...)
|
|
}
|
|
|
|
// Delete 删除
|
|
func (ud *UploadingDatabase) Delete(meta *localfile.LocalFileMeta) bool {
|
|
if meta == nil {
|
|
return false
|
|
}
|
|
|
|
meta.CompleteAbsPath()
|
|
for k, uploading := range ud.UploadingList {
|
|
if uploading.LocalFileMeta == nil {
|
|
continue
|
|
}
|
|
if uploading.LocalFileMeta.EqualLengthMD5(meta) || uploading.LocalFileMeta.Path == meta.Path {
|
|
ud.deleteIndex(k)
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Search 搜索
|
|
func (ud *UploadingDatabase) Search(meta *localfile.LocalFileMeta) *uploader.InstanceState {
|
|
if meta == nil {
|
|
return nil
|
|
}
|
|
|
|
meta.CompleteAbsPath()
|
|
ud.clearModTimeChange()
|
|
for _, uploading := range ud.UploadingList {
|
|
if uploading.LocalFileMeta == nil {
|
|
continue
|
|
}
|
|
if uploading.LocalFileMeta.EqualLengthSHA1(meta) {
|
|
return uploading.State
|
|
}
|
|
if uploading.LocalFileMeta.Path.LogicPath == meta.Path.LogicPath {
|
|
// 移除旧的信息
|
|
// 目前只是比较了文件大小
|
|
if meta.Length != uploading.LocalFileMeta.Length {
|
|
ud.Delete(meta)
|
|
return nil
|
|
}
|
|
|
|
// 覆盖数据
|
|
meta.SHA1 = uploading.LocalFileMeta.SHA1
|
|
meta.ParentFolderId = uploading.LocalFileMeta.ParentFolderId
|
|
meta.UploadOpEntity = uploading.LocalFileMeta.UploadOpEntity
|
|
return uploading.State
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ud *UploadingDatabase) clearModTimeChange() {
|
|
for i := 0; i < len(ud.UploadingList); i++ {
|
|
uploading := ud.UploadingList[i]
|
|
if uploading.LocalFileMeta == nil {
|
|
continue
|
|
}
|
|
|
|
if uploading.ModTime == -1 { // 忽略
|
|
continue
|
|
}
|
|
|
|
info, err := os.Stat(uploading.LocalFileMeta.Path.RealPath)
|
|
if err != nil {
|
|
ud.deleteIndex(i)
|
|
i--
|
|
cmdUploadVerbose.Warnf("clear invalid file path: %s, err: %s\n", uploading.LocalFileMeta.Path, err)
|
|
continue
|
|
}
|
|
|
|
if uploading.LocalFileMeta.ModTime != info.ModTime().Unix() {
|
|
ud.deleteIndex(i)
|
|
i--
|
|
cmdUploadVerbose.Infof("clear modified file path: %s\n", uploading.LocalFileMeta.Path)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// Close 关闭数据库
|
|
func (ud *UploadingDatabase) Close() error {
|
|
return ud.dataFile.Close()
|
|
}
|