From 8381e24fc48410a1a0719f08d35843e969764900 Mon Sep 17 00:00:00 2001 From: wood chen Date: Tue, 22 Oct 2024 23:52:57 +0800 Subject: [PATCH] feat(handler, schedule): improve error handling and logging for file downloads and cleanup --- go.work | 3 +++ handler/remote.go | 41 +++++++++++++++++++++++++++-------------- handler/router.go | 28 +++++++++++++++++++++++++--- schedule/cache_clean.go | 12 ++++++++++++ webp-server.go | 1 + 5 files changed, 68 insertions(+), 17 deletions(-) create mode 100644 go.work diff --git a/go.work b/go.work new file mode 100644 index 0000000..8777c4c --- /dev/null +++ b/go.work @@ -0,0 +1,3 @@ +go 1.23.1 + +use . diff --git a/handler/remote.go b/handler/remote.go index 43b365d..faaea98 100644 --- a/handler/remote.go +++ b/handler/remote.go @@ -34,20 +34,26 @@ func cleanProxyCache(cacheImagePath string) { func downloadFile(filepath string, url string) error { resp, err := http.Get(url) if err != nil { - log.Errorln("下载文件时连接到远程错误!") + log.Errorf("下载文件时连接到远程错误!上游链接: %s, 错误: %v", url, err) return err } defer resp.Body.Close() if resp.StatusCode != fiber.StatusOK { - log.Errorf("获取远程图像时远程返回 %s", resp.Status) - return fmt.Errorf("意外的状态: %s", resp.Status) + log.Errorf("获取远程图像失败。上游链接: %s, 状态码: %s", url, resp.Status) + return fmt.Errorf("意外的状态: %s, 上游链接: %s", resp.Status, url) } // 创建目标文件 - _ = os.MkdirAll(path.Dir(filepath), 0755) + err = os.MkdirAll(path.Dir(filepath), 0755) + if err != nil { + log.Errorf("创建目标目录失败。路径: %s, 错误: %v", path.Dir(filepath), err) + return err + } + out, err := os.Create(filepath) if err != nil { + log.Errorf("创建目标文件失败。文件路径: %s, 错误: %v", filepath, err) return err } defer out.Close() @@ -56,26 +62,33 @@ func downloadFile(filepath string, url string) error { buf := make([]byte, 32*1024) _, err = io.CopyBuffer(out, resp.Body, buf) if err != nil { + log.Errorf("写入文件失败。文件路径: %s, 上游链接: %s, 错误: %v", filepath, url, err) return err } + log.Infof("文件下载成功。上游链接: %s, 保存路径: %s", url, filepath) return nil } -func fetchRemoteImg(url string, subdir string) config.MetaFile { - var metadata config.MetaFile +func fetchRemoteImg(url, subdir string) (string, bool, error) { + log.Infof("正在获取远程图像: %s", url) - metadata = helper.ReadMetadata(url, "", subdir) - localRawImagePath := path.Join(config.Config.RemoteRawPath, subdir, metadata.Id) + fileName := helper.HashString(url) + localRawImagePath := path.Join(config.Config.RemoteRawPath, subdir, fileName) - if !helper.ImageExists(localRawImagePath) { - log.Info("在远程原始文件中找不到远程文件,正在获取...") - downloadFile(localRawImagePath, url) - // 重新读取更新后的元数据 - metadata = helper.WriteMetadata(url, "", subdir) + if helper.FileExists(localRawImagePath) { + log.Infof("远程图像已存在于本地: %s", localRawImagePath) + return localRawImagePath, false, nil } - return metadata + err := downloadFile(localRawImagePath, url) + if err != nil { + log.Errorf("下载远程图像失败: %v", err) + return "", false, err + } + + log.Infof("成功获取远程图像: %s", localRawImagePath) + return localRawImagePath, true, nil } func pingURL(url string) (string, int64, time.Time) { diff --git a/handler/router.go b/handler/router.go index cf07931..47a2fd3 100644 --- a/handler/router.go +++ b/handler/router.go @@ -9,6 +9,7 @@ import ( "webp_server_go/config" "webp_server_go/encoder" "webp_server_go/helper" + "webp_server_go/schedule" "github.com/gofiber/fiber/v2" log "github.com/sirupsen/logrus" @@ -76,16 +77,33 @@ func Convert(c *fiber.Ctx) error { // 文件不在 EXHAUST_PATH 中,需要处理 isLocalPath := strings.HasPrefix(matchedTarget, "./") || strings.HasPrefix(matchedTarget, "/") var rawImageAbs string + var isNewDownload bool + if isLocalPath { // 处理本地路径 localPath := strings.TrimPrefix(reqURI, matchedPrefix) rawImageAbs = path.Join(matchedTarget, localPath) + + // 检查本地文件是否存在 + if !helper.FileExists(rawImageAbs) { + log.Errorf("本地文件不存在: %s", rawImageAbs) + return c.SendStatus(fiber.StatusNotFound) + } + isNewDownload = false // 本地文件不需要清理 } else { // 处理远程URL - targetUrl, _ := url.Parse(matchedTarget) + targetUrl, err := url.Parse(matchedTarget) + if err != nil { + log.Errorf("解析目标 URL 失败: %v", err) + return c.SendStatus(fiber.StatusInternalServerError) + } remoteAddr := targetUrl.Scheme + "://" + targetUrl.Host + strings.Replace(reqURI, matchedPrefix, targetUrl.Path, 1) - metadata := fetchRemoteImg(remoteAddr, targetUrl.Host) - rawImageAbs = path.Join(config.Config.RemoteRawPath, targetUrl.Host, metadata.Id) + + rawImageAbs, isNewDownload, err = fetchRemoteImg(remoteAddr, targetUrl.Host) + if err != nil { + log.Errorf("获取远程图像失败: %v", err) + return c.SendStatus(fiber.StatusInternalServerError) + } } // 检查是否为允许的图片文件 @@ -117,6 +135,10 @@ func Convert(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusInternalServerError) } } + // 如果是新下载的远程文件,安排清理任务 + if !isLocalPath && isNewDownload { + go schedule.ScheduleCleanup(rawImageAbs) + } return c.SendFile(exhaustFilename) } diff --git a/schedule/cache_clean.go b/schedule/cache_clean.go index 1fcf07e..3628f7e 100644 --- a/schedule/cache_clean.go +++ b/schedule/cache_clean.go @@ -111,3 +111,15 @@ func CleanCache() { } } + +var cleanupDelay = 5 * time.Minute + +func ScheduleCleanup(filePath string) { + time.AfterFunc(cleanupDelay, func() { + if err := os.Remove(filePath); err != nil { + log.Warnf("清理原始文件失败: %s, 错误: %v", filePath, err) + } else { + log.Infof("成功清理原始文件: %s", filePath) + } + }) +} diff --git a/webp-server.go b/webp-server.go index 1020c0f..3209347 100644 --- a/webp-server.go +++ b/webp-server.go @@ -9,6 +9,7 @@ import ( "webp_server_go/config" "webp_server_go/encoder" "webp_server_go/handler" + schedule "webp_server_go/schedule" "github.com/gofiber/fiber/v2"