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" }