作者 yangfu
提交者 yangfu

feat: export file

  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "reflect"
  6 + "strings"
  7 +
  8 + "github.com/beego/beego/v2/core/validation"
  9 +)
  10 +
  11 +type ExportFileCommand struct {
  12 + // 文件ID
  13 + FileId int `cname:"文件ID" json:"fileId" valid:"Required"`
  14 +}
  15 +
  16 +func (cmd *ExportFileCommand) Valid(validation *validation.Validation) {
  17 +
  18 +}
  19 +
  20 +func (cmd *ExportFileCommand) ValidateCommand() error {
  21 + valid := validation.Validation{}
  22 + b, err := valid.Valid(cmd)
  23 + if err != nil {
  24 + return err
  25 + }
  26 + if !b {
  27 + elem := reflect.TypeOf(cmd).Elem()
  28 + for _, validErr := range valid.Errors {
  29 + field, isExist := elem.FieldByName(validErr.Field)
  30 + if isExist {
  31 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  32 + } else {
  33 + return fmt.Errorf(validErr.Message)
  34 + }
  35 + }
  36 + }
  37 + return nil
  38 +}
1 package service 1 package service
2 2
3 import ( 3 import (
  4 + "bytes"
4 "fmt" 5 "fmt"
  6 + "github.com/beego/beego/v2/client/httplib"
  7 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/excel"
  8 + "time"
5 9
6 "github.com/linmadan/egglib-go/core/application" 10 "github.com/linmadan/egglib-go/core/application"
7 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory" 11 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
@@ -207,3 +211,68 @@ func (fileService *FileService) AppendDataToTable(ctx *domain.Context, cmd *comm @@ -207,3 +211,68 @@ func (fileService *FileService) AppendDataToTable(ctx *domain.Context, cmd *comm
207 } 211 }
208 return result, nil 212 return result, nil
209 } 213 }
  214 +
  215 +// ExportFile 文件下载
  216 +func (fileService *FileService) ExportFile(ctx *domain.Context, cmd *command.ExportFileCommand) (interface{}, error) {
  217 + if err := cmd.ValidateCommand(); err != nil {
  218 + return nil, application.ThrowError(application.ARG_ERROR, err.Error())
  219 + }
  220 + transactionContext, err := factory.CreateTransactionContext(nil)
  221 + if err != nil {
  222 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  223 + }
  224 + if err := transactionContext.StartTransaction(); err != nil {
  225 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  226 + }
  227 + defer func() {
  228 + transactionContext.RollbackTransaction()
  229 + }()
  230 +
  231 + _, file, err := factory.FastPgFile(transactionContext, cmd.FileId)
  232 + if err != nil {
  233 + return nil, factory.FastError(err)
  234 + }
  235 +
  236 + var response = struct {
  237 + Url string `json:"url"`
  238 + Ext string `json:"ext"`
  239 + FileName string `json:"fileName"`
  240 + }{}
  241 + if file.FileType == domain.SourceFile.ToString() {
  242 + response.Url = file.FileInfo.Url
  243 + response.Ext = file.FileInfo.Ext
  244 + response.FileName = file.FileInfo.Name
  245 + return response, nil
  246 + }
  247 + _, table, err := factory.FastPgTable(transactionContext, file.FileInfo.TableId)
  248 + if err != nil {
  249 + return nil, factory.FastError(err)
  250 + }
  251 +
  252 + f, err := httplib.Get(file.FileInfo.Url).Bytes()
  253 + if err != nil {
  254 + return nil, factory.FastError(err)
  255 + }
  256 + reader := bytes.NewReader(f)
  257 + var importer *excel.Importer = excel.NewExcelImportByFile(file.FileInfo.Ext)
  258 + data, err := importer.OpenExcelFromIoReader(reader)
  259 + if err != nil {
  260 + return nil, factory.FastError(err)
  261 + }
  262 + filename := fmt.Sprintf("%v_%v.xlsx", file.FileInfo.Name, time.Now().Format("060102150405"))
  263 + path := fmt.Sprintf("public/%v", filename)
  264 + writerTo := excel.NewXLXSWriterTo(importer.Reader().Header().Columns, data)
  265 + writerTo.ToInterfaces = domain.MakeToInterfaces(table.DataFields)
  266 + if err := writerTo.Save(path); err != nil {
  267 + return nil, factory.FastError(err)
  268 + }
  269 +
  270 + response.Url = domain.DownloadUrl(filename)
  271 + response.FileName = filename
  272 + response.Ext = file.FileInfo.Ext
  273 +
  274 + if err := transactionContext.CommitTransaction(); err != nil {
  275 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  276 + }
  277 + return response, nil
  278 +}
@@ -66,23 +66,6 @@ func (tableService *TableService) ExportDataTable(ctx *domain.Context, cmd *comm @@ -66,23 +66,6 @@ func (tableService *TableService) ExportDataTable(ctx *domain.Context, cmd *comm
66 }, nil 66 }, nil
67 } 67 }
68 68
69 -func MakeToInterfaces(fields []*domain.Field) func([]string) []interface{} {  
70 - return func(input []string) []interface{} {  
71 - output := make([]interface{}, len(input))  
72 - for i, v := range input {  
73 - if i < len(fields) {  
74 - convValue, err := domain.ValueToType(v, fields[i].SQLType)  
75 - if err == nil {  
76 - output[i] = convValue  
77 - continue  
78 - }  
79 - }  
80 - output[i] = v  
81 - }  
82 - return output  
83 - }  
84 -}  
85 -  
86 func (tableService *TableService) ExportDataTableV2(ctx *domain.Context, cmd *command.TablePreviewCommand) (interface{}, error) { 69 func (tableService *TableService) ExportDataTableV2(ctx *domain.Context, cmd *command.TablePreviewCommand) (interface{}, error) {
87 if err := cmd.ValidateCommand(); err != nil { 70 if err := cmd.ValidateCommand(); err != nil {
88 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 71 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -199,7 +182,7 @@ func exportTableTo(ctx *domain.Context, cmd *command.TablePreviewCommand, table @@ -199,7 +182,7 @@ func exportTableTo(ctx *domain.Context, cmd *command.TablePreviewCommand, table
199 filename := fmt.Sprintf("%v_%v.xlsx", table.Name, time.Now().Format("060102150405")) 182 filename := fmt.Sprintf("%v_%v.xlsx", table.Name, time.Now().Format("060102150405"))
200 path := fmt.Sprintf("public/%v", filename) 183 path := fmt.Sprintf("public/%v", filename)
201 excelWriter := excel.NewXLXSWriterTo(domain.Fields(table.Fields(false)).NameArrayString(), dataTable.Data) // 184 excelWriter := excel.NewXLXSWriterTo(domain.Fields(table.Fields(false)).NameArrayString(), dataTable.Data) //
202 - excelWriter.ToInterfaces = MakeToInterfaces(table.Fields(false)) 185 + excelWriter.ToInterfaces = domain.MakeToInterfaces(table.Fields(false))
203 if err = excelWriter.Save(path); err != nil { 186 if err = excelWriter.Save(path); err != nil {
204 return nil, factory.FastError(err) 187 return nil, factory.FastError(err)
205 } 188 }
@@ -242,3 +242,20 @@ func PK() *Field { @@ -242,3 +242,20 @@ func PK() *Field {
242 Flag: PKField, 242 Flag: PKField,
243 } 243 }
244 } 244 }
  245 +
  246 +func MakeToInterfaces(fields []*Field) func([]string) []interface{} {
  247 + return func(input []string) []interface{} {
  248 + output := make([]interface{}, len(input))
  249 + for i, v := range input {
  250 + if i < len(fields) {
  251 + convValue, err := ValueToType(v, fields[i].SQLType)
  252 + if err == nil {
  253 + output[i] = convValue
  254 + continue
  255 + }
  256 + }
  257 + output[i] = v
  258 + }
  259 + return output
  260 + }
  261 +}
@@ -31,9 +31,13 @@ func (ptr *PreviewDataTableService) Preview(ctx *domain.Context, fileId int, fie @@ -31,9 +31,13 @@ func (ptr *PreviewDataTableService) Preview(ctx *domain.Context, fileId int, fie
31 if tempFile, _ := fileCache.Get(redis.KeyTemporaryFileInfo(fileId)); tempFile != nil { 31 if tempFile, _ := fileCache.Get(redis.KeyTemporaryFileInfo(fileId)); tempFile != nil {
32 isSourceFile = false 32 isSourceFile = false
33 fields = tempFile.Fields 33 fields = tempFile.Fields
34 - } else if file.FileInfo.TableId > 0 { 34 + } else if file.SourceFileId > 0 {
  35 + sourceFile, err := fileRepository.FindOne(map[string]interface{}{"fileId": file.SourceFileId})
  36 + if err != nil {
  37 + return nil, fmt.Errorf("校验文件源文件不存在")
  38 + }
35 tableRepository, _ := repository.NewTableRepository(ptr.transactionContext) 39 tableRepository, _ := repository.NewTableRepository(ptr.transactionContext)
36 - table, _ := tableRepository.FindOne(map[string]interface{}{"tableId": file.FileInfo.TableId}) 40 + table, _ := tableRepository.FindOne(map[string]interface{}{"tableId": sourceFile.FileInfo.TableId})
37 if table != nil { 41 if table != nil {
38 fields = table.Fields(false) 42 fields = table.Fields(false)
39 } 43 }
@@ -42,18 +46,16 @@ func (ptr *PreviewDataTableService) Preview(ctx *domain.Context, fileId int, fie @@ -42,18 +46,16 @@ func (ptr *PreviewDataTableService) Preview(ctx *domain.Context, fileId int, fie
42 // Load Data From Excel(python api) 46 // Load Data From Excel(python api)
43 byteCore, _ := CreateByteCoreService() 47 byteCore, _ := CreateByteCoreService()
44 response, err := byteCore.LoadDataTable(domain.ReqLoadDataTable{ 48 response, err := byteCore.LoadDataTable(domain.ReqLoadDataTable{
45 - FileId: file.FileId,  
46 - FileName: file.FileInfo.Name,  
47 - Url: file.FileInfo.Url,  
48 - Ext: file.FileInfo.Ext,  
49 - Where: where,  
50 - //FileType: file.FileType, 49 + FileId: file.FileId,
  50 + FileName: file.FileInfo.Name,
  51 + Url: file.FileInfo.Url,
  52 + Ext: file.FileInfo.Ext,
  53 + Where: where,
51 OriginalTableId: fmt.Sprintf("%v", file.FileId), 54 OriginalTableId: fmt.Sprintf("%v", file.FileId),
52 IsFromOriginalTable: isSourceFile, 55 IsFromOriginalTable: isSourceFile,
53 TableFileUrl: fileUrl, 56 TableFileUrl: fileUrl,
54 ColumnSchemas: bytelib.DomainFieldsToColumnSchemas(fields), 57 ColumnSchemas: bytelib.DomainFieldsToColumnSchemas(fields),
55 - //QueryParameters: make([]domain.QueryParameter, 0),  
56 - SortParameters: make(map[string]interface{}), 58 + SortParameters: make(map[string]interface{}),
57 }) 59 })
58 if err != nil { 60 if err != nil {
59 return nil, err 61 return nil, err
@@ -153,3 +153,11 @@ func (controller *FileController) CheckFileVerifyStatus() { @@ -153,3 +153,11 @@ func (controller *FileController) CheckFileVerifyStatus() {
153 data, err := fileService.CheckFileVerifyStatus(ParseContext(controller.BaseController), cmd) 153 data, err := fileService.CheckFileVerifyStatus(ParseContext(controller.BaseController), cmd)
154 controller.Response(data, err) 154 controller.Response(data, err)
155 } 155 }
  156 +
  157 +func (controller *FileController) ExportFile() {
  158 + fileService := service.NewFileService(nil)
  159 + cmd := &command.ExportFileCommand{}
  160 + controller.Unmarshal(cmd)
  161 + data, err := fileService.ExportFile(ParseContext(controller.BaseController), cmd)
  162 + controller.Response(data, err)
  163 +}
@@ -17,6 +17,7 @@ func init() { @@ -17,6 +17,7 @@ func init() {
17 web.Router("/data/files/search-verified-file", &controllers.FileController{}, "Post:SearchVerifiedFile") 17 web.Router("/data/files/search-verified-file", &controllers.FileController{}, "Post:SearchVerifiedFile")
18 web.Router("/data/files/cancel-verifying-file", &controllers.FileController{}, "Post:CancelVerifyingFile") 18 web.Router("/data/files/cancel-verifying-file", &controllers.FileController{}, "Post:CancelVerifyingFile")
19 web.Router("/data/files/prepare-temporary-file", &controllers.FileController{}, "Post:PrepareTemporaryFile") 19 web.Router("/data/files/prepare-temporary-file", &controllers.FileController{}, "Post:PrepareTemporaryFile")
  20 + web.Router("/data/files/export-file", &controllers.FileController{}, "Post:ExportFile")
20 21
21 web.Router("/data/file-preview", &controllers.FileController{}, "Post:FilePreview") 22 web.Router("/data/file-preview", &controllers.FileController{}, "Post:FilePreview")
22 web.Router("/data/edit-data-table", &controllers.FileController{}, "Post:EditDataTable") 23 web.Router("/data/edit-data-table", &controllers.FileController{}, "Post:EditDataTable")