作者 yangfu
提交者 yangfu

feat: export file

package command
import (
"fmt"
"reflect"
"strings"
"github.com/beego/beego/v2/core/validation"
)
type ExportFileCommand struct {
// 文件ID
FileId int `cname:"文件ID" json:"fileId" valid:"Required"`
}
func (cmd *ExportFileCommand) Valid(validation *validation.Validation) {
}
func (cmd *ExportFileCommand) ValidateCommand() error {
valid := validation.Validation{}
b, err := valid.Valid(cmd)
if err != nil {
return err
}
if !b {
elem := reflect.TypeOf(cmd).Elem()
for _, validErr := range valid.Errors {
field, isExist := elem.FieldByName(validErr.Field)
if isExist {
return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
} else {
return fmt.Errorf(validErr.Message)
}
}
}
return nil
}
... ...
package service
import (
"bytes"
"fmt"
"github.com/beego/beego/v2/client/httplib"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/excel"
"time"
"github.com/linmadan/egglib-go/core/application"
"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
}
return result, nil
}
// ExportFile 文件下载
func (fileService *FileService) ExportFile(ctx *domain.Context, cmd *command.ExportFileCommand) (interface{}, error) {
if err := cmd.ValidateCommand(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
transactionContext.RollbackTransaction()
}()
_, file, err := factory.FastPgFile(transactionContext, cmd.FileId)
if err != nil {
return nil, factory.FastError(err)
}
var response = struct {
Url string `json:"url"`
Ext string `json:"ext"`
FileName string `json:"fileName"`
}{}
if file.FileType == domain.SourceFile.ToString() {
response.Url = file.FileInfo.Url
response.Ext = file.FileInfo.Ext
response.FileName = file.FileInfo.Name
return response, nil
}
_, table, err := factory.FastPgTable(transactionContext, file.FileInfo.TableId)
if err != nil {
return nil, factory.FastError(err)
}
f, err := httplib.Get(file.FileInfo.Url).Bytes()
if err != nil {
return nil, factory.FastError(err)
}
reader := bytes.NewReader(f)
var importer *excel.Importer = excel.NewExcelImportByFile(file.FileInfo.Ext)
data, err := importer.OpenExcelFromIoReader(reader)
if err != nil {
return nil, factory.FastError(err)
}
filename := fmt.Sprintf("%v_%v.xlsx", file.FileInfo.Name, time.Now().Format("060102150405"))
path := fmt.Sprintf("public/%v", filename)
writerTo := excel.NewXLXSWriterTo(importer.Reader().Header().Columns, data)
writerTo.ToInterfaces = domain.MakeToInterfaces(table.DataFields)
if err := writerTo.Save(path); err != nil {
return nil, factory.FastError(err)
}
response.Url = domain.DownloadUrl(filename)
response.FileName = filename
response.Ext = file.FileInfo.Ext
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return response, nil
}
... ...
... ... @@ -66,23 +66,6 @@ func (tableService *TableService) ExportDataTable(ctx *domain.Context, cmd *comm
}, nil
}
func MakeToInterfaces(fields []*domain.Field) func([]string) []interface{} {
return func(input []string) []interface{} {
output := make([]interface{}, len(input))
for i, v := range input {
if i < len(fields) {
convValue, err := domain.ValueToType(v, fields[i].SQLType)
if err == nil {
output[i] = convValue
continue
}
}
output[i] = v
}
return output
}
}
func (tableService *TableService) ExportDataTableV2(ctx *domain.Context, cmd *command.TablePreviewCommand) (interface{}, error) {
if err := cmd.ValidateCommand(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
... ... @@ -199,7 +182,7 @@ func exportTableTo(ctx *domain.Context, cmd *command.TablePreviewCommand, table
filename := fmt.Sprintf("%v_%v.xlsx", table.Name, time.Now().Format("060102150405"))
path := fmt.Sprintf("public/%v", filename)
excelWriter := excel.NewXLXSWriterTo(domain.Fields(table.Fields(false)).NameArrayString(), dataTable.Data) //
excelWriter.ToInterfaces = MakeToInterfaces(table.Fields(false))
excelWriter.ToInterfaces = domain.MakeToInterfaces(table.Fields(false))
if err = excelWriter.Save(path); err != nil {
return nil, factory.FastError(err)
}
... ...
... ... @@ -242,3 +242,20 @@ func PK() *Field {
Flag: PKField,
}
}
func MakeToInterfaces(fields []*Field) func([]string) []interface{} {
return func(input []string) []interface{} {
output := make([]interface{}, len(input))
for i, v := range input {
if i < len(fields) {
convValue, err := ValueToType(v, fields[i].SQLType)
if err == nil {
output[i] = convValue
continue
}
}
output[i] = v
}
return output
}
}
... ...
... ... @@ -31,9 +31,13 @@ func (ptr *PreviewDataTableService) Preview(ctx *domain.Context, fileId int, fie
if tempFile, _ := fileCache.Get(redis.KeyTemporaryFileInfo(fileId)); tempFile != nil {
isSourceFile = false
fields = tempFile.Fields
} else if file.FileInfo.TableId > 0 {
} else if file.SourceFileId > 0 {
sourceFile, err := fileRepository.FindOne(map[string]interface{}{"fileId": file.SourceFileId})
if err != nil {
return nil, fmt.Errorf("校验文件源文件不存在")
}
tableRepository, _ := repository.NewTableRepository(ptr.transactionContext)
table, _ := tableRepository.FindOne(map[string]interface{}{"tableId": file.FileInfo.TableId})
table, _ := tableRepository.FindOne(map[string]interface{}{"tableId": sourceFile.FileInfo.TableId})
if table != nil {
fields = table.Fields(false)
}
... ... @@ -42,18 +46,16 @@ func (ptr *PreviewDataTableService) Preview(ctx *domain.Context, fileId int, fie
// Load Data From Excel(python api)
byteCore, _ := CreateByteCoreService()
response, err := byteCore.LoadDataTable(domain.ReqLoadDataTable{
FileId: file.FileId,
FileName: file.FileInfo.Name,
Url: file.FileInfo.Url,
Ext: file.FileInfo.Ext,
Where: where,
//FileType: file.FileType,
FileId: file.FileId,
FileName: file.FileInfo.Name,
Url: file.FileInfo.Url,
Ext: file.FileInfo.Ext,
Where: where,
OriginalTableId: fmt.Sprintf("%v", file.FileId),
IsFromOriginalTable: isSourceFile,
TableFileUrl: fileUrl,
ColumnSchemas: bytelib.DomainFieldsToColumnSchemas(fields),
//QueryParameters: make([]domain.QueryParameter, 0),
SortParameters: make(map[string]interface{}),
SortParameters: make(map[string]interface{}),
})
if err != nil {
return nil, err
... ...
... ... @@ -153,3 +153,11 @@ func (controller *FileController) CheckFileVerifyStatus() {
data, err := fileService.CheckFileVerifyStatus(ParseContext(controller.BaseController), cmd)
controller.Response(data, err)
}
func (controller *FileController) ExportFile() {
fileService := service.NewFileService(nil)
cmd := &command.ExportFileCommand{}
controller.Unmarshal(cmd)
data, err := fileService.ExportFile(ParseContext(controller.BaseController), cmd)
controller.Response(data, err)
}
... ...
... ... @@ -17,6 +17,7 @@ func init() {
web.Router("/data/files/search-verified-file", &controllers.FileController{}, "Post:SearchVerifiedFile")
web.Router("/data/files/cancel-verifying-file", &controllers.FileController{}, "Post:CancelVerifyingFile")
web.Router("/data/files/prepare-temporary-file", &controllers.FileController{}, "Post:PrepareTemporaryFile")
web.Router("/data/files/export-file", &controllers.FileController{}, "Post:ExportFile")
web.Router("/data/file-preview", &controllers.FileController{}, "Post:FilePreview")
web.Router("/data/edit-data-table", &controllers.FileController{}, "Post:EditDataTable")
... ...