You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sonic/service/theme/multipartzip_fetcher.go

88 lines
2.5 KiB
Go

package theme
import (
"context"
"errors"
"io"
"mime/multipart"
"os"
"path/filepath"
"strings"
"go.uber.org/fx"
"github.com/go-sonic/sonic/model/dto"
"github.com/go-sonic/sonic/util"
"github.com/go-sonic/sonic/util/xerr"
)
type multipartZipThemeFetcherImpl struct {
fx.Out
PropertyScanner PropertyScanner
}
func NewMultipartZipThemeFetcher(propertyScanner PropertyScanner) ThemeFetcher {
return &multipartZipThemeFetcherImpl{
PropertyScanner: propertyScanner,
}
}
func (m *multipartZipThemeFetcherImpl) FetchTheme(ctx context.Context, file interface{}) (*dto.ThemeProperty, error) {
themeFileHeader, ok := file.(*multipart.FileHeader)
if !ok {
return nil, xerr.WithStatus(nil, xerr.StatusBadRequest).WithMsg("not support")
}
tempDir := os.TempDir()
srcThemeFile, err := themeFileHeader.Open()
if err != nil {
return nil, xerr.WithStatus(err, xerr.StatusBadRequest).WithMsg("upload theme file error")
}
defer srcThemeFile.Close()
fileName := themeFileHeader.Filename
if !strings.HasSuffix(fileName, ".zip") {
return nil, xerr.WithStatus(nil, xerr.StatusBadRequest).WithMsg("not zip file")
}
diskFilePath := filepath.Join(tempDir, fileName)
if util.FileIsExisted(diskFilePath) {
err = os.Remove(diskFilePath)
if err != nil {
return nil, xerr.WithStatus(err, xerr.StatusInternalServerError)
}
}
diskFile, err := os.OpenFile(diskFilePath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o444)
if err != nil && !errors.Is(err, os.ErrExist) {
return nil, xerr.WithStatus(err, xerr.StatusInternalServerError).WithMsg("create file error")
}
defer diskFile.Close()
_, err = io.Copy(diskFile, srcThemeFile)
if err != nil {
return nil, xerr.WithStatus(err, xerr.StatusInternalServerError).WithMsg("save file error")
}
_, err = util.Unzip(filepath.Join(tempDir, fileName), filepath.Join(tempDir, strings.TrimSuffix(fileName, ".zip")))
if err != nil {
return nil, xerr.WithStatus(err, xerr.StatusInternalServerError).WithMsg("unzip file error")
}
dest := filepath.Join(tempDir, strings.TrimSuffix(fileName, ".zip"))
themeProperty, err := m.PropertyScanner.ReadThemeProperty(ctx, dest)
if err == nil && themeProperty != nil {
return themeProperty, nil
}
dirEntrys, err := os.ReadDir(dest)
for _, dirEntry := range dirEntrys {
if !dirEntry.IsDir() {
continue
}
themeProperty, err = m.PropertyScanner.ReadThemeProperty(ctx, filepath.Join(dest, dirEntry.Name()))
if err == nil && themeProperty != nil {
return themeProperty, nil
}
}
return nil, err
}