logarchivedownloadlogic.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // Code scaffolded by goctl. Safe to edit.
  2. // goctl 1.10.2
  3. package systemlog
  4. import (
  5. "archive/zip"
  6. "context"
  7. "fmt"
  8. "io"
  9. "net/http"
  10. "os"
  11. "path/filepath"
  12. "udeServer/internal/apierr"
  13. "udeServer/internal/log"
  14. "udeServer/internal/svc"
  15. "udeServer/internal/types"
  16. "github.com/zeromicro/go-zero/core/logx"
  17. )
  18. type LogArchiveDownloadLogic struct {
  19. logx.Logger
  20. ctx context.Context
  21. svcCtx *svc.ServiceContext
  22. }
  23. // 归档打包下载(zip)
  24. func NewLogArchiveDownloadLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LogArchiveDownloadLogic {
  25. return &LogArchiveDownloadLogic{
  26. Logger: logx.WithContext(ctx),
  27. ctx: ctx,
  28. svcCtx: svcCtx,
  29. }
  30. }
  31. // LogArchiveDownload streams the selected archive files back as one zip.
  32. // The response is written to w directly (no unified envelope); the handler
  33. // therefore must not call httpx.OkJsonCtx afterwards.
  34. func (l *LogArchiveDownloadLogic) LogArchiveDownload(w http.ResponseWriter, req *types.LogArchiveDownloadReq) error {
  35. if len(req.Ids) == 0 {
  36. return apierr.BadRequest("ids 不能为空")
  37. }
  38. if l.svcCtx.MinioClient == nil {
  39. return apierr.New(500, "MinIO客户端未加载,无法下载归档(检查t_config的file_*配置)")
  40. }
  41. log.RecordDebug(l.ctx, "开始下载Ids:%+v的归档!", req.Ids)
  42. list, err := l.svcCtx.LogArchiveRecordModel.FindByIds(l.ctx, req.Ids)
  43. if err != nil {
  44. log.RecordError(l.ctx, err)
  45. return apierr.New(500, "查询归档记录失败")
  46. }
  47. if len(list) == 0 {
  48. return apierr.New(404, "归档记录不存在")
  49. }
  50. w.Header().Set("Content-Type", "application/zip")
  51. w.Header().Set("Content-Disposition", "attachment; filename=archives.zip")
  52. zipWriter := zip.NewWriter(w)
  53. defer func() {
  54. _ = zipWriter.Close()
  55. }()
  56. for i := range list {
  57. v := &list[i]
  58. filePath, err := l.svcCtx.MinioClient.DownloadFile(l.ctx, v.ArchiveFileKey)
  59. if err != nil || filePath == "" {
  60. log.RecordError(l.ctx, fmt.Errorf("下载归档文件失败[ID:%d]: %v", v.Id, err))
  61. return apierr.New(500, "下载归档文件失败")
  62. }
  63. if err := copyArchiveIntoZip(zipWriter, filePath, v.ArchiveFileKey); err != nil {
  64. log.RecordError(l.ctx, err)
  65. }
  66. }
  67. log.RecordDebug(l.ctx, "Ids:%+v的归档下载成功!", req.Ids)
  68. return nil
  69. }
  70. // copyArchiveIntoZip adds one archive file as a zip entry (temp file removed
  71. // afterwards).
  72. func copyArchiveIntoZip(zipWriter *zip.Writer, filePath, archiveFileKey string) error {
  73. // 1.删除临时文件
  74. defer func() {
  75. _ = os.Remove(filePath)
  76. }()
  77. // 2.打开文件
  78. file, err := os.Open(filePath)
  79. if err != nil {
  80. return fmt.Errorf("打开文件失败[%s]: %w", archiveFileKey, err)
  81. }
  82. defer func() {
  83. _ = file.Close()
  84. }()
  85. // 3.文件打包
  86. zipFileName := filepath.Base(archiveFileKey)
  87. zipEntryWriter, err := zipWriter.Create(zipFileName)
  88. if err != nil {
  89. return fmt.Errorf("创建ZIP条目失败[%s]: %w", archiveFileKey, err)
  90. }
  91. if _, err := io.Copy(zipEntryWriter, file); err != nil {
  92. return fmt.Errorf("写入ZIP条目失败[%s]: %w", archiveFileKey, err)
  93. }
  94. return nil
  95. }