⚡ Optimize hash logic
This commit is contained in:
parent
c6311c466f
commit
f7ab3bfb18
@ -212,36 +212,57 @@ func AnalyzeAttachment(file models.Attachment) error {
|
||||
}
|
||||
|
||||
func HashAttachment(file models.Attachment) (hash string, err error) {
|
||||
if file.Destination != models.AttachmentDstTemporary {
|
||||
err = fmt.Errorf("attachment isn't in temporary storage, unable to hash")
|
||||
return
|
||||
const chunkSize = 32 * 1024
|
||||
|
||||
destMap := viper.GetStringMapString("destinations.temporary")
|
||||
destPath := filepath.Join(destMap["path"], file.Uuid)
|
||||
|
||||
// Check if the file exists
|
||||
fileInfo, err := os.Stat(destPath)
|
||||
if os.IsNotExist(err) {
|
||||
return "", fmt.Errorf("file does not exist: %v", err)
|
||||
}
|
||||
|
||||
destMap := viper.GetStringMap("destinations.temporary")
|
||||
|
||||
var dest models.LocalDestination
|
||||
rawDest, _ := jsoniter.Marshal(destMap)
|
||||
_ = jsoniter.Unmarshal(rawDest, &dest)
|
||||
|
||||
dst := filepath.Join(dest.Path, file.Uuid)
|
||||
if _, err = os.Stat(dst); os.IsNotExist(err) {
|
||||
err = fmt.Errorf("attachment doesn't exists in temporary storage: %v", err)
|
||||
return
|
||||
}
|
||||
var in *os.File
|
||||
in, err = os.Open(dst)
|
||||
// Open the file
|
||||
inFile, err := os.Open(destPath)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("unable to open file: %v", err)
|
||||
return
|
||||
return "", fmt.Errorf("unable to open file: %v", err)
|
||||
}
|
||||
defer in.Close()
|
||||
defer inFile.Close()
|
||||
|
||||
hasher := sha256.New()
|
||||
if _, err = io.Copy(hasher, in); err != nil {
|
||||
err = fmt.Errorf("unable to hash: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Hash the first 32KB
|
||||
buf := make([]byte, chunkSize)
|
||||
if _, err := inFile.Read(buf); err != nil && err != io.EOF {
|
||||
return "", fmt.Errorf("error reading file: %v", err)
|
||||
}
|
||||
hasher.Write(buf)
|
||||
|
||||
// Hash the middle 32KB
|
||||
middleOffset := fileInfo.Size() / 2
|
||||
if _, err := inFile.Seek(middleOffset, io.SeekStart); err != nil {
|
||||
return "", fmt.Errorf("error seeking to middle: %v", err)
|
||||
}
|
||||
if _, err := inFile.Read(buf); err != nil && err != io.EOF {
|
||||
return "", fmt.Errorf("error reading middle: %v", err)
|
||||
}
|
||||
hasher.Write(buf)
|
||||
|
||||
// Hash the last 32KB
|
||||
endOffset := fileInfo.Size() - chunkSize
|
||||
if _, err := inFile.Seek(endOffset, io.SeekStart); err != nil {
|
||||
return "", fmt.Errorf("error seeking to end: %v", err)
|
||||
}
|
||||
if _, err := inFile.Read(buf); err != nil && err != io.EOF {
|
||||
return "", fmt.Errorf("error reading end: %v", err)
|
||||
}
|
||||
hasher.Write(buf)
|
||||
|
||||
// Hash with the file metadata
|
||||
hasher.Write([]byte(fmt.Sprintf("%d", file.Size)))
|
||||
|
||||
// Return the combined hash
|
||||
hash = hex.EncodeToString(hasher.Sum(nil))
|
||||
return
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user