Skip to content

Commit

Permalink
fix: 修复上传中文名压缩包文件
Browse files Browse the repository at this point in the history
  • Loading branch information
Ambition9186 committed Jun 25, 2024
1 parent f0e9055 commit bc608b3
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 48 deletions.
117 changes: 90 additions & 27 deletions bcs-services/bcs-bscp/cmd/api-server/service/config_import.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,27 @@ type configImport struct {
}

// TemplateConfigFileImport Import template config file
func (c *configImport) TemplateConfigFileImport(w http.ResponseWriter, r *http.Request) { // nolint
//
//nolint:funlen
func (c *configImport) TemplateConfigFileImport(w http.ResponseWriter, r *http.Request) {
kt := kit.MustGetKit(r.Context())

unzipStr := r.Header.Get("X-Bscp-Unzip")
unzip, _ := strconv.ParseBool(unzipStr)

tmplSpaceIdStr := chi.URLParam(r, "template_space_id")
tmplSpaceID, _ := strconv.Atoi(tmplSpaceIdStr)
if tmplSpaceID == 0 {
_ = render.Render(w, r, rest.BadRequest(errors.New("validation parameter fail")))
return
}

fileName := chi.URLParam(r, "filename")
if fileName == "" {
_ = render.Render(w, r, rest.BadRequest(errors.New("file name cannot be empty")))
return
}

// Validation size
if r.ContentLength > constant.MaxUploadContentLength {
_ = render.Render(w, r, rest.BadRequest(errors.New("request body size exceeds 100MB")))
Expand All @@ -86,13 +99,37 @@ func (c *configImport) TemplateConfigFileImport(w http.ResponseWriter, r *http.R
// 组合上一次读取
combinedReader := io.MultiReader(bytes.NewReader(buffer[:n]), r.Body)

identifyFileType := archive.IdentifyFileType(buffer[:n])
var (
tempDir string
err error
)

tempDir, err := archive.Unpack(combinedReader, identifyFileType)
if err != nil {
_ = render.Render(w, r, rest.BadRequest(err))
return
// 默认当文件处理
identifyFileType := archive.Unknown
// 自动解压
if unzip {
identifyFileType = archive.IdentifyFileType(buffer[:n])
}

if identifyFileType != archive.Unknown {
tempDir, err = archive.Unpack(combinedReader, identifyFileType)
if err != nil {
_ = render.Render(w, r, rest.BadRequest(err))
return
}
} else {
tempDir, err = os.MkdirTemp("", "templateConfigItem-")
if err != nil {
_ = render.Render(w, r, rest.BadRequest(err))
return
}

if err = saveFile(combinedReader, tempDir, fileName); err != nil {
_ = render.Render(w, r, rest.BadRequest(err))
return
}
}

defer func() { _ = os.RemoveAll(tempDir) }()

// 先扫描一遍文件夹,获取路径和名称,
Expand All @@ -102,6 +139,11 @@ func (c *configImport) TemplateConfigFileImport(w http.ResponseWriter, r *http.R
return
}

if err = c.checkFileConfictsWithTemplates(kt, uint32(tmplSpaceID), fileItems); err != nil {
_ = render.Render(w, r, rest.BadRequest(err))
return
}

folder, err := c.processAndUploadDirectoryFiles(kt, tempDir, len(fileItems))
if err != nil {
_ = render.Render(w, r, rest.BadRequest(err))
Expand All @@ -120,8 +162,7 @@ func (c *configImport) TemplateConfigFileImport(w http.ResponseWriter, r *http.R
})
}

// 压缩包里面文件过多会导致sql占位符不够
// 需要分批处理
// 压缩包里面文件过多会导致sql占位符不够, 需要分批处理
batchSize := constant.UploadBatchSize
templateItem := map[string]*pbcs.ListTemplateByTupleResp_Item{}
for i := 0; i < len(templateItems); i += batchSize {
Expand Down Expand Up @@ -164,14 +205,13 @@ func (c *configImport) TemplateConfigFileImport(w http.ResponseWriter, r *http.R
newItem.FileMode = string(table.Unix)
nonExist = append(nonExist, newItem)
} else {
exist = append(exist, &types.TemplateItem{
Id: data.GetTemplate().GetId(),
FileMode: data.GetTemplateRevision().GetSpec().GetFileMode(),
Memo: data.GetTemplate().GetSpec().GetMemo(),
Privilege: data.GetTemplateRevision().GetSpec().GetPermission().GetPrivilege(),
User: data.GetTemplateRevision().GetSpec().GetPermission().GetUser(),
UserGroup: data.GetTemplateRevision().GetSpec().GetPermission().GetUserGroup(),
})
newItem.Id = data.GetTemplate().GetId()
newItem.FileMode = data.GetTemplateRevision().GetSpec().GetFileMode()
newItem.Memo = data.GetTemplate().GetSpec().GetMemo()
newItem.Privilege = data.GetTemplateRevision().GetSpec().GetPermission().GetPrivilege()
newItem.User = data.GetTemplateRevision().GetSpec().GetPermission().GetUser()
newItem.UserGroup = data.GetTemplateRevision().GetSpec().GetPermission().GetUserGroup()
exist = append(exist, newItem)
}
}
msg := "上传完成"
Expand All @@ -188,12 +228,14 @@ func (c *configImport) TemplateConfigFileImport(w http.ResponseWriter, r *http.R
}

// ConfigFileImport Import config file
func (c *configImport) ConfigFileImport(w http.ResponseWriter, r *http.Request) { // nolint
//
//nolint:funlen
func (c *configImport) ConfigFileImport(w http.ResponseWriter, r *http.Request) {
kt := kit.MustGetKit(r.Context())
// Ensure r.Body is closed after reading
defer r.Body.Close()

unzipStr := chi.URLParam(r, "unzip")
unzipStr := r.Header.Get("X-Bscp-Unzip")
unzip, _ := strconv.ParseBool(unzipStr)

appIdStr := chi.URLParam(r, "app_id")
Expand All @@ -204,7 +246,7 @@ func (c *configImport) ConfigFileImport(w http.ResponseWriter, r *http.Request)
}
kt.AppID = uint32(appId)

fileName := r.Header.Get("X-Bscp-File-Name")
fileName := chi.URLParam(r, "filename")
if fileName == "" {
_ = render.Render(w, r, rest.BadRequest(errors.New("file name cannot be empty")))
return
Expand Down Expand Up @@ -267,9 +309,7 @@ func (c *configImport) ConfigFileImport(w http.ResponseWriter, r *http.Request)
return
}

// 存在冲突直接抛出错误,无需再上传到存储桶中
// 检测某服务下非模板配置冲突
if err = c.getAllConfigFileByApp(kt, fileItems); err != nil {
if err = c.checkFileConfictsWithNonTemplates(kt, fileItems); err != nil {
_ = render.Render(w, r, rest.BadRequest(err))
return
}
Expand All @@ -292,8 +332,7 @@ func (c *configImport) ConfigFileImport(w http.ResponseWriter, r *http.Request)
})
}

// 压缩包里面文件过多会导致sql占位符不够
// 需要分批处理
// 压缩包里面文件过多会导致sql占位符不够, 需要分批处理
batchSize := constant.UploadBatchSize
configItem := map[string]*pbci.ConfigItem{}
for i := 0; i < len(configItems); i += batchSize {
Expand Down Expand Up @@ -586,8 +625,9 @@ func sortByPathName(myStructs []*types.TemplateItem) {
})
}

// getAllConfigFileByApp 获取某个服务下的所有非模板配置文件
func (c *configImport) getAllConfigFileByApp(kt *kit.Kit, newFiles []tools.CIUniqueKey) error {
// 检测与非配置文件冲突
func (c *configImport) checkFileConfictsWithNonTemplates(kt *kit.Kit, files []tools.CIUniqueKey) error {
// 获取服务下的所有非模板配置文件
items, err := c.cfgClient.ListConfigItems(kt.RpcCtx(), &pbcs.ListConfigItemsReq{
BizId: kt.BizID,
AppId: kt.AppID,
Expand All @@ -596,16 +636,39 @@ func (c *configImport) getAllConfigFileByApp(kt *kit.Kit, newFiles []tools.CIUni
if err != nil {
return err
}

filesToCompare := []tools.CIUniqueKey{}
for _, v := range items.GetDetails() {
filesToCompare = append(filesToCompare, tools.CIUniqueKey{
Name: v.Spec.Name,
Path: v.Spec.Path,
})
}

return tools.DetectFilePathConflicts(files, filesToCompare)
}

// 检测与模板套餐下的文件冲突
func (c *configImport) checkFileConfictsWithTemplates(kt *kit.Kit, templateSpaceId uint32,
files []tools.CIUniqueKey) error {
// 获取该空间下所有文件
items, err := c.cfgClient.ListTemplates(kt.RpcCtx(), &pbcs.ListTemplatesReq{
BizId: kt.BizID,
TemplateSpaceId: templateSpaceId,
All: true,
})
if err != nil {
return err
}
filesToCompare := []tools.CIUniqueKey{}
for _, v := range items.GetDetails() {
filesToCompare = append(filesToCompare, tools.CIUniqueKey{
Name: v.Spec.Name,
Path: v.Spec.Path,
})
}

return tools.DetectFilePathConflicts(newFiles, filesToCompare)
return tools.DetectFilePathConflicts(files, filesToCompare)
}

// 临时保存文件
Expand Down
15 changes: 8 additions & 7 deletions bcs-services/bcs-bscp/cmd/api-server/service/routers.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,17 @@ func (p *proxy) routers() http.Handler {
})

// 导入模板压缩包
r.Route("/api/v1/config/biz/{biz_id}/template_spaces/{template_space_id}/templates/import", func(r chi.Router) {
r.Use(p.authorizer.UnifiedAuthentication)
r.Use(p.authorizer.BizVerified)
r.Use(p.HttpServerHandledTotal("", "TemplateConfigFileImport"))
r.Post("/", p.configImportService.TemplateConfigFileImport)
r.Route("/api/v1/config/biz/{biz_id}/template_spaces/{template_space_id}/templates/import/{filename}",
func(r chi.Router) {
r.Use(p.authorizer.UnifiedAuthentication)
r.Use(p.authorizer.BizVerified)
r.Use(p.HttpServerHandledTotal("", "TemplateConfigFileImport"))
r.Post("/", p.configImportService.TemplateConfigFileImport)

})
})

// 导入配置压缩包
r.Route("/api/v1/config/biz/{biz_id}/apps/{app_id}/config_item/import/{unzip}", func(r chi.Router) {
r.Route("/api/v1/config/biz/{biz_id}/apps/{app_id}/config_item/import/{filename}", func(r chi.Router) {
r.Use(p.authorizer.UnifiedAuthentication)
r.Use(p.authorizer.BizVerified)
r.Use(p.HttpServerHandledTotal("", "ConfigFileImport"))
Expand Down
13 changes: 0 additions & 13 deletions bcs-services/bcs-bscp/cmd/config-server/service/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,19 +245,6 @@ func (s *Service) AddTmplsToTmplSets(ctx context.Context, req *pbcs.AddTmplsToTm
*pbcs.AddTmplsToTmplSetsResp, error) {
grpcKit := kit.FromGrpcContext(ctx)

// validate input param
idsLen := len(req.TemplateIds)
if idsLen == 0 || idsLen > constant.ArrayInputLenLimit {
return nil, fmt.Errorf("the length of template ids is %d, it must be within the range of [1,%d]",
idsLen, constant.ArrayInputLenLimit)
}

idsLen2 := len(req.TemplateSetIds)
if idsLen2 == 0 || idsLen2 > constant.ArrayInputLenLimit {
return nil, fmt.Errorf("the length of template set ids is %d, it must be within the range of [1,%d]",
idsLen2, constant.ArrayInputLenLimit)
}

res := []*meta.ResourceAttribute{
{Basic: meta.Basic{Type: meta.Biz, Action: meta.FindBusinessResource}, BizID: req.BizId},
}
Expand Down
2 changes: 1 addition & 1 deletion bcs-services/bcs-bscp/pkg/runtime/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func CORS(next http.Handler) http.Handler {
"X-Bkapi-File-Content-Overwrite",
"X-Bscp-App-Id",
"X-Bscp-Template-Space-Id",
"X-Bscp-File-Name",
"X-Bscp-Unzip",
"X-Bscp-Upload-Id",
"X-Bscp-Part-Num",
}
Expand Down

0 comments on commit bc608b3

Please sign in to comment.