67 lines
1.5 KiB
Go
67 lines
1.5 KiB
Go
package pdfcache
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"crypto/sha256"
|
||
|
|
"encoding/hex"
|
||
|
|
"io"
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Cache 工艺文件 PDF 本地预缓存。
|
||
|
|
// 以文件名的安全哈希作为缓存键,避免任意文件名带来的路径穿越与特殊字符问题;
|
||
|
|
// 首次访问时回源 MES 下载并落盘,后续直接读本地缓存,实现离线可查看工艺文件。
|
||
|
|
type Cache struct {
|
||
|
|
dir string
|
||
|
|
}
|
||
|
|
|
||
|
|
func New(dir string) *Cache {
|
||
|
|
return &Cache{dir: strings.TrimSpace(dir)}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Enabled 是否启用本地缓存(目录非空)。
|
||
|
|
func (c *Cache) Enabled() bool {
|
||
|
|
return c.dir != ""
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get 返回缓存文件路径;若不存在返回 ok=false。
|
||
|
|
func (c *Cache) Get(name string) (path string, ok bool) {
|
||
|
|
if !c.Enabled() {
|
||
|
|
return "", false
|
||
|
|
}
|
||
|
|
p := filepath.Join(c.dir, key(name))
|
||
|
|
if _, err := os.Stat(p); err == nil {
|
||
|
|
return p, true
|
||
|
|
}
|
||
|
|
return "", false
|
||
|
|
}
|
||
|
|
|
||
|
|
// Put 写入缓存,返回写入路径(仅在启用时生效)。
|
||
|
|
func (c *Cache) Put(name string, data []byte) (string, error) {
|
||
|
|
if !c.Enabled() {
|
||
|
|
return "", nil
|
||
|
|
}
|
||
|
|
if err := os.MkdirAll(c.dir, 0o755); err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
p := filepath.Join(c.dir, key(name))
|
||
|
|
if err := os.WriteFile(p, data, 0o644); err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
return p, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Open 以只读方式打开缓存文件。
|
||
|
|
func (c *Cache) Open(name string) (io.ReadCloser, error) {
|
||
|
|
p, ok := c.Get(name)
|
||
|
|
if !ok {
|
||
|
|
return nil, os.ErrNotExist
|
||
|
|
}
|
||
|
|
return os.Open(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
func key(name string) string {
|
||
|
|
h := sha256.Sum256([]byte(name))
|
||
|
|
return hex.EncodeToString(h[:]) + ".pdf"
|
||
|
|
}
|