webp_server_go/helper/metadata.go
wood chen c9cb32b0da 尝试优化内存占用
feat(encoder): optimize prefetch images with worker pool and progress bar
refactor(handler): improve downloadFile function with error handling
refactor(helper): use streaming JSON encoder for metadata
chore(webp-server): update server config with write buffer size
2024-10-22 17:26:43 +08:00

92 lines
2.6 KiB
Go

package helper
import (
"encoding/json"
"net/url"
"os"
"path"
"webp_server_go/config"
log "github.com/sirupsen/logrus"
)
func getId(p string) (string, string, string) {
var id string
if config.ProxyMode {
return HashString(p), "", ""
}
parsed, _ := url.Parse(p)
width := parsed.Query().Get("width")
height := parsed.Query().Get("height")
max_width := parsed.Query().Get("max_width")
max_height := parsed.Query().Get("max_height")
// santizedPath will be /webp_server.jpg?width=200\u0026height=\u0026max_width=\u0026max_height= in local mode when requesting /webp_server.jpg?width=200
// santizedPath will be https://docs.webp.sh/images/webp_server.jpg?width=400 in proxy mode when requesting /images/webp_server.jpg?width=400 with IMG_PATH = https://docs.webp.sh
santizedPath := parsed.Path + "?width=" + width + "&height=" + height + "&max_width=" + max_width + "&max_height=" + max_height
id = HashString(santizedPath)
return id, path.Join(config.Config.ImgPath, parsed.Path), santizedPath
}
func ReadMetadata(p, etag string, subdir string) config.MetaFile {
// try to read metadata, if we can't read, create one
var metadata config.MetaFile
var id, _, _ = getId(p)
if buf, err := os.ReadFile(path.Join(config.Config.MetadataPath, subdir, id+".json")); err != nil {
// First time reading metadata, create one
WriteMetadata(p, etag, subdir)
return ReadMetadata(p, etag, subdir)
} else {
err = json.Unmarshal(buf, &metadata)
if err != nil {
log.Warnf("解组元数据错误、可能损坏的文件、重建...: %s", err)
WriteMetadata(p, etag, subdir)
return ReadMetadata(p, etag, subdir)
}
return metadata
}
}
func WriteMetadata(p, etag string, subdir string) config.MetaFile {
_ = os.MkdirAll(path.Join(config.Config.MetadataPath, subdir), 0755)
id, filepath, sant := getId(p)
data := config.MetaFile{
Id: id,
}
if etag != "" {
data.Path = p
data.Checksum = HashString(etag)
} else {
data.Path = sant
data.Checksum = HashFile(filepath)
}
// 使用流式 JSON 编码器
file, err := os.Create(path.Join(config.Config.MetadataPath, subdir, data.Id+".json"))
if err != nil {
log.Errorf("无法创建元数据文件: %v", err)
return data
}
defer file.Close()
encoder := json.NewEncoder(file)
if err := encoder.Encode(data); err != nil {
log.Errorf("无法编码元数据: %v", err)
}
return data
}
func DeleteMetadata(p string, subdir string) {
var id, _, _ = getId(p)
metadataPath := path.Join(config.Config.MetadataPath, subdir, id+".json")
err := os.Remove(metadataPath)
if err != nil {
log.Warnln("删除元数据失败", err)
}
}