fix(backend): serve original content with byte-range support
deploy / deploy (push) Successful in 1m1s
deploy / deploy (push) Successful in 1m1s
GetContent streamed the whole file with a plain 200/io.Copy and no Accept-Ranges, so the browser couldn't seek or scrub audio/video opened from the viewer. It now serves seekable bodies (the disk store returns an *os.File) via http.ServeContent, which advertises Accept-Ranges and answers Range requests with 206 Partial Content; non-seekable bodies still fall back to a plain stream. Adds an integration test asserting a ranged request returns 206 with the right Content-Range and bytes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -407,9 +407,20 @@ func (h *FileHandler) GetContent(c *gin.Context) {
|
||||
if c.Query("inline") == "1" {
|
||||
disposition = "inline"
|
||||
}
|
||||
name := ""
|
||||
if res.OriginalName != nil {
|
||||
name = *res.OriginalName
|
||||
c.Header("Content-Disposition",
|
||||
fmt.Sprintf("%s; filename=%q", disposition, *res.OriginalName))
|
||||
fmt.Sprintf("%s; filename=%q", disposition, name))
|
||||
}
|
||||
|
||||
// Serve with byte-range support when the body is seekable (it is for the
|
||||
// disk store): http.ServeContent advertises Accept-Ranges and answers Range
|
||||
// requests with 206 Partial Content, which is what lets the browser scrub and
|
||||
// seek within audio/video. Fall back to a plain stream otherwise.
|
||||
if seeker, ok := res.Body.(io.ReadSeeker); ok {
|
||||
http.ServeContent(c.Writer, c.Request, name, time.Time{}, seeker)
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusOK)
|
||||
io.Copy(c.Writer, res.Body) //nolint:errcheck
|
||||
|
||||
Reference in New Issue
Block a user