0
0
mirror of https://github.com/go-gitea/gitea.git synced 2025-11-10 13:31:01 -05:00

Allow to display embed images/pdfs when SERVE_DIRECT was enabled on MinIO storage (#35882)

Releated issue: https://github.com/go-gitea/gitea/issues/30487

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
lifegpc
2025-11-10 13:31:25 +08:00
committed by GitHub
parent 60314cb688
commit 1c8c56503f
3 changed files with 31 additions and 5 deletions

View File

@@ -250,6 +250,7 @@ func (a *AzureBlobStorage) Delete(path string) error {
func (a *AzureBlobStorage) URL(path, name, _ string, reqParams url.Values) (*url.URL, error) {
blobClient := a.getBlobClient(path)
// TODO: OBJECT-STORAGE-CONTENT-TYPE: "browser inline rendering images/PDF" needs proper Content-Type header from storage
startTime := time.Now()
u, err := blobClient.GetSASURL(sas.BlobPermissions{
Read: true,

View File

@@ -279,20 +279,44 @@ func (m *MinioStorage) Delete(path string) error {
}
// URL gets the redirect URL to a file. The presigned link is valid for 5 minutes.
func (m *MinioStorage) URL(path, name, method string, serveDirectReqParams url.Values) (*url.URL, error) {
func (m *MinioStorage) URL(storePath, name, method string, serveDirectReqParams url.Values) (*url.URL, error) {
// copy serveDirectReqParams
reqParams, err := url.ParseQuery(serveDirectReqParams.Encode())
if err != nil {
return nil, err
}
// TODO it may be good to embed images with 'inline' like ServeData does, but we don't want to have to read the file, do we?
reqParams.Set("response-content-disposition", "attachment; filename=\""+quoteEscaper.Replace(name)+"\"")
// Here we might not know the real filename, and it's quite inefficient to detect the mine type by pre-fetching the object head.
// So we just do a quick detection by extension name, at least if works for the "View Raw File" for an LFS file on the Web UI.
// Detect content type by extension name, only support the well-known safe types for inline rendering.
// TODO: OBJECT-STORAGE-CONTENT-TYPE: need a complete solution and refactor for Azure in the future
ext := path.Ext(name)
inlineExtMimeTypes := map[string]string{
".png": "image/png",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".gif": "image/gif",
".webp": "image/webp",
".avif": "image/avif",
// ATTENTION! Don't support unsafe types like HTML/SVG due to security concerns: they can contain JS code, and maybe they need proper Content-Security-Policy
// HINT: PDF-RENDER-SANDBOX: PDF won't render in sandboxed context, it seems fine to render it inline
".pdf": "application/pdf",
// TODO: refactor with "modules/public/mime_types.go", for example: "DetectWellKnownSafeInlineMimeType"
}
if mimeType, ok := inlineExtMimeTypes[ext]; ok {
reqParams.Set("response-content-type", mimeType)
reqParams.Set("response-content-disposition", "inline")
} else {
reqParams.Set("response-content-disposition", fmt.Sprintf(`attachment; filename="%s"`, quoteEscaper.Replace(name)))
}
expires := 5 * time.Minute
if method == http.MethodHead {
u, err := m.client.PresignedHeadObject(m.ctx, m.bucket, m.buildMinioPath(path), expires, reqParams)
u, err := m.client.PresignedHeadObject(m.ctx, m.bucket, m.buildMinioPath(storePath), expires, reqParams)
return u, convertMinioErr(err)
}
u, err := m.client.PresignedGetObject(m.ctx, m.bucket, m.buildMinioPath(path), expires, reqParams)
u, err := m.client.PresignedGetObject(m.ctx, m.bucket, m.buildMinioPath(storePath), expires, reqParams)
return u, convertMinioErr(err)
}

View File

@@ -95,6 +95,7 @@ func getFileReader(ctx gocontext.Context, repoID int64, blob *git.Blob) (buf []b
meta, err := git_model.GetLFSMetaObjectByOid(ctx, repoID, pointer.Oid)
if err != nil { // fallback to a plain file
fi.lfsMeta = &pointer
log.Warn("Unable to access LFS pointer %s in repo %d: %v", pointer.Oid, repoID, err)
return buf, dataRc, fi, nil
}