diff --git a/Dockerfile b/Dockerfile index 0bb59df..afc222b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,25 +1,24 @@ -FROM golang:1.23 AS builder +FROM golang:1.23-bookworm AS builder +ARG IMG_PATH=/opt/pics ARG EXHAUST_PATH=/opt/exhaust RUN apt update && apt install --no-install-recommends libvips-dev -y && mkdir /build COPY go.mod /build RUN cd /build && go mod download COPY . /build -RUN cd /build && sed -i "s|\"\"|\"${EXHAUST_PATH}\"|g" config.json \ +RUN cd /build && sed -i "s|.\/pics|${IMG_PATH}|g" config.json \ + && sed -i "s|\"\"|\"${EXHAUST_PATH}\"|g" config.json \ && sed -i 's/127.0.0.1/0.0.0.0/g' config.json \ && go build -ldflags="-s -w" -o webp-server . -FROM alpine:latest +FROM debian:bookworm-slim + +RUN apt update && apt install --no-install-recommends libvips ca-certificates -y && rm -rf /var/lib/apt/lists/* && rm -rf /var/cache/apt/archives/* -RUN apk update && \ - apk add --no-cache libvips ca-certificates && \ - rm -rf /var/cache/apk/* - COPY --from=builder /build/webp-server /usr/bin/webp-server COPY --from=builder /build/config.json /etc/config.json - + WORKDIR /opt VOLUME /opt/exhaust CMD ["/usr/bin/webp-server", "--config", "/etc/config.json"] - diff --git a/handler/remote.go b/handler/remote.go index faaea98..4230491 100644 --- a/handler/remote.go +++ b/handler/remote.go @@ -3,6 +3,7 @@ package handler import ( "fmt" "io" + "mime" "net/http" "os" "path" @@ -125,3 +126,37 @@ func pingURL(url string) (string, int64, time.Time) { return etag, size, lastModified } + +func streamFile(c *fiber.Ctx, filePath string) error { + file, err := os.Open(filePath) + if err != nil { + log.Errorf("无法打开文件: %s, 错误: %v", filePath, err) + return c.Status(fiber.StatusInternalServerError).SendString("无法打开文件") + } + defer file.Close() + + stat, err := file.Stat() + if err != nil { + log.Errorf("无法获取文件信息: %s, 错误: %v", filePath, err) + return c.Status(fiber.StatusInternalServerError).SendString("无法获取文件信息") + } + + contentType := mime.TypeByExtension(path.Ext(filePath)) + if contentType == "" { + contentType = "application/octet-stream" + } + + c.Set(fiber.HeaderContentType, contentType) + c.Set(fiber.HeaderContentLength, strconv.FormatInt(stat.Size(), 10)) + + log.Infof("开始流式传输文件: %s, 大小: %d bytes", filePath, stat.Size()) + + err = c.SendStream(file) + if err != nil { + log.Errorf("文件流式传输失败: %s, 错误: %v", filePath, err) + return err + } + + log.Infof("文件流式传输完成: %s", filePath) + return nil +} diff --git a/handler/router.go b/handler/router.go index 0b3e2ee..e6f30b8 100644 --- a/handler/router.go +++ b/handler/router.go @@ -72,7 +72,7 @@ func Convert(c *fiber.Ctx) error { // 检查文件是否已经在 EXHAUST_PATH 中 if helper.FileExists(exhaustFilename) { log.Infof("文件已存在于 EXHAUST_PATH,直接提供服务: %s", exhaustFilename) - return c.SendFile(exhaustFilename) + return streamFile(c, exhaustFilename) } // 文件不在 EXHAUST_PATH 中,需要处理 @@ -110,7 +110,7 @@ func Convert(c *fiber.Ctx) error { // 检查是否为允许的图片文件 if !helper.IsAllowedImageFile(filename) { log.Infof("不允许的文件类型或非图片文件: %s", reqURI) - return c.SendFile(rawImageAbs) + return streamFile(c, rawImageAbs) } // 处理图片 @@ -148,5 +148,5 @@ func Convert(c *fiber.Ctx) error { go schedule.ScheduleCleanup(rawImageAbs) } - return c.SendFile(exhaustFilename) + return streamFile(c, exhaustFilename) }