From 252dc319c6dd1321378fa7ceda6cd1b6a36dec66 Mon Sep 17 00:00:00 2001 From: user123456 Date: Wed, 18 Jun 2025 14:55:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=A6=BB=E7=BA=BF=E5=8C=85?= =?UTF-8?q?=E4=BD=93=E7=A7=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/imagetar.go | 50 +++++++++++++++------- src/public/images.html | 94 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 126 insertions(+), 18 deletions(-) diff --git a/src/imagetar.go b/src/imagetar.go index d08de5b..ff01e69 100644 --- a/src/imagetar.go +++ b/src/imagetar.go @@ -171,8 +171,9 @@ func NewImageStreamer(config *ImageStreamerConfig) *ImageStreamer { // StreamOptions 下载选项 type StreamOptions struct { - Platform string - Compression bool + Platform string + Compression bool + UseCompressedLayers bool // 是否保存原始压缩层,默认true } // StreamImageToWriter 流式下载镜像到Writer @@ -336,12 +337,24 @@ func (is *ImageStreamer) streamDockerFormatWithReturn(ctx context.Context, tarWr return err } - uncompressedSize, err := partial.UncompressedSize(layer) - if err != nil { - return err + var layerSize int64 + var layerReader io.ReadCloser + + // 根据配置选择使用压缩层或未压缩层 + if options != nil && options.UseCompressedLayers { + layerSize, err = layer.Size() + if err != nil { + return err + } + layerReader, err = layer.Compressed() + } else { + layerSize, err = partial.UncompressedSize(layer) + if err != nil { + return err + } + layerReader, err = layer.Uncompressed() } - - layerReader, err := layer.Uncompressed() + if err != nil { return err } @@ -349,7 +362,7 @@ func (is *ImageStreamer) streamDockerFormatWithReturn(ctx context.Context, tarWr layerTarHeader := &tar.Header{ Name: layerDir + "/layer.tar", - Size: uncompressedSize, + Size: layerSize, Mode: 0644, } @@ -628,6 +641,7 @@ func handleDirectImageDownload(c *gin.Context) { imageRef := strings.ReplaceAll(imageParam, "_", "/") platform := c.Query("platform") tag := c.DefaultQuery("tag", "") + useCompressed := c.DefaultQuery("compressed", "true") == "true" if tag != "" && !strings.Contains(imageRef, ":") && !strings.Contains(imageRef, "@") { imageRef = imageRef + ":" + tag @@ -653,8 +667,9 @@ func handleDirectImageDownload(c *gin.Context) { } options := &StreamOptions{ - Platform: platform, - Compression: false, + Platform: platform, + Compression: false, + UseCompressedLayers: useCompressed, } ctx := c.Request.Context() @@ -670,8 +685,9 @@ func handleDirectImageDownload(c *gin.Context) { // handleSimpleBatchDownload 处理批量下载 func handleSimpleBatchDownload(c *gin.Context) { var req struct { - Images []string `json:"images" binding:"required"` - Platform string `json:"platform"` + Images []string `json:"images" binding:"required"` + Platform string `json:"platform"` + UseCompressedLayers *bool `json:"useCompressedLayers"` } if err := c.ShouldBindJSON(&req); err != nil { @@ -710,9 +726,15 @@ func handleSimpleBatchDownload(c *gin.Context) { return } + useCompressed := true // 默认启用原始压缩层 + if req.UseCompressedLayers != nil { + useCompressed = *req.UseCompressedLayers + } + options := &StreamOptions{ - Platform: req.Platform, - Compression: false, + Platform: req.Platform, + Compression: false, + UseCompressedLayers: useCompressed, } ctx := c.Request.Context() diff --git a/src/public/images.html b/src/public/images.html index b82f010..a566894 100644 --- a/src/public/images.html +++ b/src/public/images.html @@ -399,6 +399,67 @@ 100% { transform: rotate(360deg); } } + /* 切换开关样式 */ + .switch-container { + display: flex; + align-items: center; + gap: 0.75rem; + margin-bottom: 1.5rem; + } + + .switch { + position: relative; + display: inline-block; + width: 50px; + height: 24px; + } + + .switch input { + opacity: 0; + width: 0; + height: 0; + } + + .slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: var(--muted); + transition: 0.2s; + border-radius: 24px; + border: 1px solid var(--border); + } + + .slider:before { + position: absolute; + content: ""; + height: 18px; + width: 18px; + left: 2px; + bottom: 2px; + background-color: white; + transition: 0.2s; + border-radius: 50%; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); + } + + input:checked + .slider { + background-color: var(--primary); + } + + input:checked + .slider:before { + transform: translateX(26px); + } + + .switch-label { + font-weight: 500; + color: var(--foreground); + cursor: pointer; + } + .hidden { display: none; } @@ -559,6 +620,14 @@ +
+ + +
+