Files

105 lines
2.3 KiB
Go

package bundle_packager
import (
"archive/zip"
"bytes"
"io"
"strings"
"github.com/langgenius/dify-plugin-daemon/pkg/entities/bundle_entities"
"github.com/langgenius/dify-plugin-daemon/pkg/utils/parser"
)
type MemoryZipBundlePackager struct {
GenericBundlePackager
zipReader *zip.Reader
}
func NewMemoryZipBundlePackager(zipFile []byte) (*MemoryZipBundlePackager, error) {
// try read manifest file
zipReader, err := zip.NewReader(bytes.NewReader(zipFile), int64(len(zipFile)))
if err != nil {
return nil, err
}
manifestFile, err := zipReader.Open("manifest.yaml")
if err != nil {
return nil, err
}
defer manifestFile.Close()
manifestBytes, err := io.ReadAll(manifestFile)
if err != nil {
return nil, err
}
bundle, err := parser.UnmarshalYamlBytes[bundle_entities.Bundle](manifestBytes)
if err != nil {
return nil, err
}
// collect files starts with README
extraFiles := make(map[string]*bytes.Buffer)
for _, file := range zipReader.File {
if strings.HasPrefix(file.Name, "README") {
buffer := bytes.NewBuffer([]byte{})
readFile, err := file.Open()
if err != nil {
return nil, err
}
defer readFile.Close()
io.Copy(buffer, readFile)
extraFiles[file.Name] = buffer
}
}
packager := &MemoryZipBundlePackager{
GenericBundlePackager: *NewGenericBundlePackager(&bundle, extraFiles),
zipReader: zipReader,
}
// walk through the zip file and load the assets
for _, file := range zipReader.File {
// if file starts with "_assets/"
// FIXES: https://github.com/langgenius/dify/issues/32650
// zip file is os-independent, `/` is the separator
if strings.HasPrefix(file.Name, "_assets/") {
// load the asset
asset, err := file.Open()
if err != nil {
return nil, err
}
defer asset.Close()
assetBytes, err := io.ReadAll(asset)
if err != nil {
return nil, err
}
// trim the prefix "_assets/"
assetName := strings.TrimPrefix(file.Name, "_assets/")
packager.assets[assetName] = bytes.NewBuffer(assetBytes)
}
}
return packager, nil
}
func (p *MemoryZipBundlePackager) Save() error {
return nil
}
func (p *MemoryZipBundlePackager) ReadFile(path string) ([]byte, error) {
// read the file from the zip reader
file, err := p.zipReader.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
return io.ReadAll(file)
}