github.com/soulteary/pocket-bookcase@v0.0.0-20240428065142-0b5a9a0fc98a/internal/http/response/file.go (about) 1 package response 2 3 import ( 4 "fmt" 5 "io" 6 "net/http" 7 8 "github.com/gin-gonic/gin" 9 "github.com/soulteary/pocket-bookcase/internal/model" 10 ) 11 12 // SendFile sends file to client with caching header 13 func SendFile(c *gin.Context, storageDomain model.StorageDomain, path string) { 14 c.Header("Cache-Control", "public, max-age=86400") 15 16 if !storageDomain.FileExists(path) { 17 c.AbortWithStatus(http.StatusNotFound) 18 return 19 } 20 21 info, err := storageDomain.Stat(path) 22 if err != nil { 23 c.AbortWithStatus(http.StatusInternalServerError) 24 return 25 } 26 27 c.Header("ETag", fmt.Sprintf("W/%x-%x", info.ModTime().Unix(), info.Size())) 28 29 // TODO: Find a better way to send the file to the client from the FS, probably making a 30 // conversion between afero.Fs and http.FileSystem to use c.FileFromFS. 31 fileContent, err := storageDomain.FS().Open(path) 32 if err != nil { 33 c.AbortWithStatus(http.StatusInternalServerError) 34 return 35 } 36 37 _, err = io.Copy(c.Writer, fileContent) 38 if err != nil { 39 c.AbortWithStatus(http.StatusInternalServerError) 40 return 41 } 42 }