package service import ( "context" "crypto/md5" "encoding/hex" "fmt" "git.hpds.cc/Component/logging" "github.com/minio/minio-go/v7/pkg/credentials" "hpds-iot-web/config" "hpds-iot-web/internal/proto" "hpds-iot-web/model" "io" "mime/multipart" "net/http" "strings" "time" "xorm.io/xorm" "github.com/minio/minio-go/v7" ) type FileService interface { UploadFile(ctx context.Context, req proto.UploadFileRequest) (rsp *proto.BaseResponse, err error) UploadFileToMinIo(ctx context.Context, srcFile *multipart.FileHeader, scene string, datasetId, creator int64, dataType int) (data *model.FileManager, err error) FileList(ctx context.Context, req proto.DatasetItemRequest) (rsp *proto.BaseResponse, err error) FileLabel(ctx context.Context, req proto.FileLabelRequest) (rsp *proto.BaseResponse, err error) } func NewFileService(cfg *config.WebConfig, engine *xorm.Engine, logger *logging.Logger) FileService { return &repo{ AppConfig: cfg, engine: engine, logger: logger, } } func (rp *repo) UploadFile(ctx context.Context, req proto.UploadFileRequest) (rsp *proto.BaseResponse, err error) { rsp = new(proto.BaseResponse) select { case <-ctx.Done(): err = fmt.Errorf("超时/取消") rsp.Code = http.StatusInternalServerError rsp.Status = http.StatusText(http.StatusInternalServerError) rsp.Message = "超时/取消" rsp.Err = ctx.Err() return rsp, ctx.Err() default: list := make([]*model.FileManager, len(req.Files)) fileUrl := make([]string, len(req.Files)) for k := range req.Files { fileItem, err := rp.UploadFileToMinIo(ctx, req.Files[k], req.Scene, req.DatasetId, req.Creator, req.DataType) if err != nil { goto ReturnPoint } list[k] = fileItem list[k].DatasetId = req.DatasetId fileUrl[k] = fileItem.AccessUrl } _, err = rp.engine.Insert(list) res := proto.UploadResponse{ Url: strings.Join(fileUrl, ","), } rsp.Code = http.StatusOK rsp.Status = http.StatusText(http.StatusOK) rsp.Message = "成功" rsp.Data = res rsp.Err = err return rsp, err } ReturnPoint: if err != nil { rsp.Code = http.StatusInternalServerError rsp.Status = http.StatusText(http.StatusInternalServerError) rsp.Err = err rsp.Message = "失败" } return rsp, err } func (rp *repo) UploadFileToMinIo(ctx context.Context, srcFile *multipart.FileHeader, scene string, datasetId, creator int64, dataType int) (data *model.FileManager, err error) { file, err := srcFile.Open() defer func(file multipart.File) { _ = file.Close() }(file) if err != nil { return nil, err } fileName := srcFile.Filename opt := &minio.Options{ Creds: credentials.NewStaticV4(rp.AppConfig.Minio.AccessKeyId, rp.AppConfig.Minio.SecretAccessKey, ""), Secure: false, } minioClient, err := minio.New(rp.AppConfig.Minio.Endpoint, opt) if err != nil { return nil, err } objPath := fmt.Sprintf("%s/%s/%s", scene, time.Now().Format("20060102"), fileName) if datasetId > 0 { var h bool item := new(model.Dataset) h, err = rp.engine.ID(datasetId).Get(item) if err != nil { return nil, err } if h && len(item.StoreName) > 0 { objPath = fmt.Sprintf("%s/%s/%s/%s", scene, item.StoreName, time.Now().Format("20060102"), fileName) } } //bucketName := fmt.Sprintf("jky-data/%s/%s", scene, time.Now().Format("20060102")) info, err := minioClient.PutObject(ctx, rp.AppConfig.Minio.Bucket, objPath, file, srcFile.Size, minio.PutObjectOptions{ContentType: "application/octet-stream"}) if err != nil { return nil, err } fmt.Println("info =====> ", info) accessUrl := fmt.Sprintf("%s://%s/jky-data/%s", rp.AppConfig.Minio.Protocol, rp.AppConfig.Minio.Endpoint, objPath) md5hash := md5.New() if _, err := io.Copy(md5hash, file); err != nil { return nil, err } data = new(model.FileManager) data.FileName = fileName data.Scene = scene data.AccessUrl = accessUrl data.FileSize = srcFile.Size data.DataType = dataType data.DatasetId = datasetId data.Creator = creator data.FileMd5 = hex.EncodeToString(md5hash.Sum(nil)) data.CreateAt = time.Now().Unix() data.UpdateAt = time.Now().Unix() return data, nil } func (rp *repo) FileList(ctx context.Context, req proto.DatasetItemRequest) (rsp *proto.BaseResponse, err error) { rsp = new(proto.BaseResponse) select { case <-ctx.Done(): err = fmt.Errorf("超时/取消") rsp.Code = http.StatusInternalServerError rsp.Status = http.StatusText(http.StatusInternalServerError) rsp.Message = "超时/取消" rsp.Err = ctx.Err() return rsp, ctx.Err() default: data := make([]model.FileManager, 0) count, err := rp.engine.Where("(? = 0 or dataset_id = ?)", req.DatasetId, req.DatasetId). And("(? = 0 or data_type = ?)", req.DataType, req.DataType). Limit(int(req.Size), int(((req.Page)-1)*req.Size)). FindAndCount(&data) if err != nil { goto ReturnPoint } rsp.Code = http.StatusOK rsp.Status = http.StatusText(http.StatusOK) rsp.Message = "成功" rsp = FillPaging(count, req.Page, req.Size, data, rsp) rsp.Err = err return rsp, err } ReturnPoint: if err != nil { rsp.Code = http.StatusInternalServerError rsp.Status = http.StatusText(http.StatusInternalServerError) rsp.Err = err rsp.Message = "失败" } return rsp, err } func (rp *repo) FileLabel(ctx context.Context, req proto.FileLabelRequest) (rsp *proto.BaseResponse, err error) { rsp = new(proto.BaseResponse) select { case <-ctx.Done(): err = fmt.Errorf("超时/取消") rsp.Code = http.StatusInternalServerError rsp.Status = http.StatusText(http.StatusInternalServerError) rsp.Message = "超时/取消" rsp.Err = ctx.Err() return rsp, ctx.Err() default: item := new(model.FileManager) var h bool h, err = rp.engine.ID(req.FileId).Get(item) if err != nil { goto ReturnPoint } if !h { err = fmt.Errorf("未能找到对应的文件") goto ReturnPoint } if req.IsDisease { item.IsDisease = 1 } else { item.IsDisease = 2 } _, err = rp.engine.ID(req.FileId).Cols("is_disease").Update(item) if err != nil { goto ReturnPoint } rsp.Code = http.StatusOK rsp.Status = http.StatusText(http.StatusOK) rsp.Message = "成功" rsp.Err = err return rsp, err } ReturnPoint: if err != nil { rsp.Code = http.StatusInternalServerError rsp.Status = http.StatusText(http.StatusInternalServerError) rsp.Err = err rsp.Message = "失败" } return rsp, err }