lazy compute file

This commit is contained in:
Celogeek 2022-01-02 16:39:49 +01:00
parent 31441a3e3c
commit 234a63f208
Signed by: celogeek
GPG Key ID: E6B7BDCFC446233A
2 changed files with 126 additions and 122 deletions

View File

@ -29,25 +29,28 @@ func (p *Piwigo) FileExists(md5 string) bool {
} }
func (p *Piwigo) CheckUploadFile(file *piwigotools.FileToUpload, stat *piwigotools.FileToUploadStat) (err error) { func (p *Piwigo) CheckUploadFile(file *piwigotools.FileToUpload, stat *piwigotools.FileToUploadStat) (err error) {
if !file.Checked() { if file.Checked() {
if file.MD5() == "" { return nil
}
if file.MD5() == nil {
stat.Fail() stat.Fail()
stat.Check() stat.Check()
err = fmt.Errorf("%s: checksum error", file.FullPath()) err = fmt.Errorf("%s: checksum error", *file.FullPath())
stat.Error("CheckUploadFile", file.FullPath(), err) stat.Error("CheckUploadFile", *file.FullPath(), err)
return return
} }
if p.FileExists(file.MD5()) { if p.FileExists(*file.MD5()) {
stat.Skip() stat.Skip()
stat.Check() stat.Check()
err = fmt.Errorf("%s: file already exists", file.FullPath()) err = fmt.Errorf("%s: file already exists", *file.FullPath())
return return
} }
stat.Check() stat.Check()
stat.AddBytes(file.Size()) stat.AddBytes(*file.Size())
}
return nil return nil
} }
@ -59,7 +62,7 @@ func (p *Piwigo) Upload(file *piwigotools.FileToUpload, stat *piwigotools.FileTo
wg := &sync.WaitGroup{} wg := &sync.WaitGroup{}
chunks, err := file.Base64Chunker() chunks, err := file.Base64Chunker()
if err != nil { if err != nil {
stat.Error("Base64Chunker", file.FullPath(), err) stat.Error("Base64Chunker", *file.FullPath(), err)
return return
} }
@ -77,7 +80,7 @@ func (p *Piwigo) Upload(file *piwigotools.FileToUpload, stat *piwigotools.FileTo
var resp *FileUploadResult var resp *FileUploadResult
data := &url.Values{} data := &url.Values{}
data.Set("original_sum", file.MD5()) data.Set("original_sum", *file.MD5())
data.Set("original_filename", file.Name) data.Set("original_filename", file.Name)
data.Set("check_uniqueness", "true") data.Set("check_uniqueness", "true")
if file.CreatedAt() != nil { if file.CreatedAt() != nil {
@ -95,7 +98,7 @@ func (p *Piwigo) Upload(file *piwigotools.FileToUpload, stat *piwigotools.FileTo
err = nil err = nil
break break
} }
stat.Error(fmt.Sprintf("Upload %d", i), file.FullPath(), err) stat.Error(fmt.Sprintf("Upload %d", i), *file.FullPath(), err)
} }
if err != nil { if err != nil {
@ -104,7 +107,7 @@ func (p *Piwigo) Upload(file *piwigotools.FileToUpload, stat *piwigotools.FileTo
} }
if hasVideoJS { if hasVideoJS {
switch file.Ext() { switch *file.Ext() {
case "ogg", "ogv", "mp4", "m4v", "webm", "webmv": case "ogg", "ogv", "mp4", "m4v", "webm", "webmv":
p.VideoJSSync(resp.ImageId) p.VideoJSSync(resp.ImageId)
} }
@ -118,7 +121,7 @@ func (p *Piwigo) UploadChunk(file *piwigotools.FileToUpload, chunks chan *piwigo
for chunk := range chunks { for chunk := range chunks {
var err error var err error
data := &url.Values{ data := &url.Values{
"original_sum": []string{file.MD5()}, "original_sum": []string{*file.MD5()},
"position": []string{fmt.Sprint(chunk.Position)}, "position": []string{fmt.Sprint(chunk.Position)},
"type": []string{"file"}, "type": []string{"file"},
"data": []string{chunk.Buffer.String()}, "data": []string{chunk.Buffer.String()},
@ -128,7 +131,7 @@ func (p *Piwigo) UploadChunk(file *piwigotools.FileToUpload, chunks chan *piwigo
if err == nil { if err == nil {
break break
} }
stat.Error(fmt.Sprintf("UploadChunk %d", i), file.FullPath(), err) stat.Error(fmt.Sprintf("UploadChunk %d", i), *file.FullPath(), err)
} }
stat.Commit(chunk.Size) stat.Commit(chunk.Size)
if err != nil { if err != nil {
@ -193,7 +196,7 @@ func (p *Piwigo) ScanTree(
Name: dir.Name(), Name: dir.Name(),
CategoryId: parentCategoryId, CategoryId: parentCategoryId,
} }
if !filter.Has(file.Ext()) { if !filter.Has(*file.Ext()) {
continue continue
} }
stat.Add() stat.Add()

View File

@ -15,9 +15,10 @@ import (
) )
type FileInfo struct { type FileInfo struct {
md5 string fullpath *string
size int64 md5 *string
ext string size *int64
ext *string
createdAt *TimeResult createdAt *TimeResult
} }
@ -26,73 +27,119 @@ type FileToUpload struct {
Name string Name string
CategoryId int CategoryId int
info *FileInfo info FileInfo
} }
func (f *FileToUpload) FullPath() string { func (f *FileToUpload) FullPath() *string {
return filepath.Join(f.Dir, f.Name) if f.info.fullpath != nil {
return f.info.fullpath
}
fp := filepath.Join(f.Dir, f.Name)
f.info.fullpath = &fp
return f.info.fullpath
} }
func (f *FileToUpload) Info() *FileInfo { func (f *FileToUpload) Size() *int64 {
if f.info != nil { if f.info.size != nil {
return f.info return f.info.size
} }
file, err := os.Open(f.FullPath()) st, err := os.Stat(*f.FullPath())
if err != nil {
return nil
}
size := st.Size()
f.info.size = &size
return f.info.size
}
func (f *FileToUpload) Ext() *string {
if f.info.ext != nil {
return f.info.ext
}
ext := strings.ToLower(filepath.Ext(f.Name)[1:])
f.info.ext = &ext
return f.info.ext
}
func (f *FileToUpload) MD5() *string {
if f.info.md5 != nil {
return f.info.md5
}
file, err := os.Open(*f.FullPath())
if err != nil { if err != nil {
return nil return nil
} }
defer file.Close() defer file.Close()
st, err := file.Stat()
if err != nil {
return nil
}
hash := md5.New() hash := md5.New()
if _, err = io.Copy(hash, file); err != nil { if _, err = io.Copy(hash, file); err != nil {
return nil return nil
} }
checksum := fmt.Sprintf("%x", hash.Sum(nil)) checksum := fmt.Sprintf("%x", hash.Sum(nil))
f.info.md5 = &checksum
info := FileInfo{ return f.info.md5
size: st.Size(),
md5: checksum,
createdAt: f.exifCreatedAt(),
}
f.info = &info
return f.info
}
func (f *FileToUpload) Checked() bool {
return f.info != nil
}
func (f *FileToUpload) MD5() string {
if info := f.Info(); info != nil {
return info.md5
}
return ""
}
func (f *FileToUpload) Size() int64 {
if info := f.Info(); info != nil {
return info.size
}
return -1
}
func (f *FileToUpload) Ext() string {
return strings.ToLower(filepath.Ext(f.Name)[1:])
} }
func (f *FileToUpload) CreatedAt() *TimeResult { func (f *FileToUpload) CreatedAt() *TimeResult {
if info := f.Info(); info != nil { if f.info.createdAt != nil {
return info.createdAt return f.info.createdAt
} }
et, err := exiftool.NewExiftool()
if err != nil {
return nil return nil
}
defer et.Close()
var createdAt *time.Time
var CreateDateFormat = "2006:01:02 15:04:05-07:00"
fileInfos := et.ExtractMetadata(*f.FullPath())
for _, fileInfo := range fileInfos {
if fileInfo.Err != nil {
continue
}
var t time.Time
for k, v := range fileInfo.Fields {
switch k {
case "CreateDate":
offset, ok := fileInfo.Fields["OffsetTime"]
if !ok {
offset = "+00:00"
}
v := fmt.Sprintf("%s%s", v, offset)
t, err = time.Parse(CreateDateFormat, v)
case "CreationDate":
t, err = time.Parse(CreateDateFormat, fmt.Sprint(v))
default:
continue
}
if err != nil {
continue
}
if createdAt == nil || createdAt.After(t) {
createdAt = &t
}
}
}
if createdAt != nil {
result := TimeResult(*createdAt)
f.info.createdAt = &result
}
return f.info.createdAt
}
func (f *FileToUpload) Checked() bool {
return f.info.md5 != nil
} }
var ( var (
@ -108,7 +155,7 @@ type FileToUploadChunk struct {
} }
func (f *FileToUpload) Base64Chunker() (chan *FileToUploadChunk, error) { func (f *FileToUpload) Base64Chunker() (chan *FileToUploadChunk, error) {
fh, err := os.Open(f.FullPath()) fh, err := os.Open(*f.FullPath())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -144,49 +191,3 @@ func (f *FileToUpload) Base64Chunker() (chan *FileToUploadChunk, error) {
return out, nil return out, nil
} }
func (f *FileToUpload) exifCreatedAt() *TimeResult {
et, err := exiftool.NewExiftool()
if err != nil {
return nil
}
defer et.Close()
var createdAt *time.Time
var CreateDateFormat = "2006:01:02 15:04:05-07:00"
fileInfos := et.ExtractMetadata(f.FullPath())
for _, fileInfo := range fileInfos {
if fileInfo.Err != nil {
continue
}
var t time.Time
for k, v := range fileInfo.Fields {
switch k {
case "CreateDate":
offset, ok := fileInfo.Fields["OffsetTime"]
if !ok {
offset = "+00:00"
}
v := fmt.Sprintf("%s%s", v, offset)
t, err = time.Parse(CreateDateFormat, v)
case "CreationDate":
t, err = time.Parse(CreateDateFormat, fmt.Sprint(v))
default:
continue
}
if err != nil {
continue
}
if createdAt == nil || createdAt.After(t) {
createdAt = &t
}
}
}
if createdAt != nil {
result := TimeResult(*createdAt)
return &result
}
return nil
}