fix: allow browser caching for file downloads (#2349)

This commit is contained in:
Weijie Zhao
2026-03-05 00:43:03 +08:00
committed by GitHub
parent 740ec183d9
commit 54d977532e
2 changed files with 24 additions and 1 deletions

View File

@@ -380,9 +380,21 @@ func GetProjectBackground(c *echo.Context) error {
return err
}
// Override the global no-store directive so browsers can cache background images.
// no-cache allows caching but requires revalidation via If-Modified-Since.
c.Response().Header().Set("Cache-Control", "no-cache")
// Set Last-Modified header if we have the file stat, so clients can decide whether to use cached files
if stat != nil {
c.Response().Header().Set(echo.HeaderLastModified, stat.ModTime().UTC().Format(http.TimeFormat))
modTime := stat.ModTime().UTC()
c.Response().Header().Set(echo.HeaderLastModified, modTime.Format(http.TimeFormat))
// Check If-Modified-Since and return 304 if the file hasn't changed
if ifModSince := c.Request().Header.Get("If-Modified-Since"); ifModSince != "" {
if t, err := http.ParseTime(ifModSince); err == nil && !modTime.After(t) {
return c.NoContent(http.StatusNotModified)
}
}
}
// Serve the file

View File

@@ -217,8 +217,19 @@ func GetTaskAttachment(c *echo.Context) error {
c.Response().Header().Set("Content-Type", mimeToReturn)
c.Response().Header().Set("Content-Length", strconv.FormatUint(taskAttachment.File.Size, 10))
c.Response().Header().Set("Last-Modified", taskAttachment.File.Created.UTC().Format(http.TimeFormat))
// Override the global no-store directive so browsers can cache attachments.
// no-cache allows caching but requires revalidation via If-Modified-Since.
c.Response().Header().Set("Cache-Control", "no-cache")
if config.FilesType.GetString() == "s3" {
// Check If-Modified-Since and return 304 if the file hasn't changed.
// http.ServeContent handles this automatically for local files.
if ifModSince := c.Request().Header.Get("If-Modified-Since"); ifModSince != "" {
if t, parseErr := http.ParseTime(ifModSince); parseErr == nil && !taskAttachment.File.Created.UTC().After(t) {
return c.NoContent(http.StatusNotModified)
}
}
// s3 files cannot use http.ServeContent as it requires a Seekable file
// so we stream the file content directly to the response
_, err = io.Copy(c.Response(), taskAttachment.File.File)