fix(webdav): cache a file the built-in extractors find no image in, as for Tika

This commit is contained in:
Dominik Schmidt committed 2026-11-06 12:00:12 +01:00
1 parent 44bee90ec2
commit f41f46c258
4 files changed
+59 -21

No files matched your search

+1 -7
View File
@@ -2,10 +2,4 @@ package preprocessor
import "errors"
var (
ErrNoImageFromAudioFile = errors.New("preprocessor: could not extract image from audio file")
ErrNoConverterForExtractedImageFromGgsFile = errors.New("preprocessor: could not find converter for image extracted from ggs file")
ErrNoConverterForExtractedImageFromAudioFile = errors.New("preprocessor: could not find converter for image extracted from audio file")
ErrNoConverterForExtractedImageFromGgpFile = errors.New("preprocessor: could not find converter for image extracted from ggp file")
ErrNoThumbnail = errors.New("preprocessor: the document has no thumbnail")
)
var ErrNoThumbnail = errors.New("preprocessor: the document has no thumbnail")
@@ -86,7 +86,7 @@ func (g GgsDecoder) Convert(r io.Reader) (*Image, error) {
return &Image{ContentType: "image/png", Data: data}, nil
}
}
return nil, errors.Errorf("%s not found", g.thumbnailpath)
return nil, ErrNoThumbnail
}
// AudioDecoder is a converter for the audio file.
@@ -111,12 +111,8 @@ func (i AudioDecoder) Convert(r io.Reader) (*Image, error) {
}
picture := m.Picture()
if picture == nil {
return nil, ErrNoImageFromAudioFile
}
if !strings.HasPrefix(picture.MIMEType, "image/") {
return nil, ErrNoConverterForExtractedImageFromAudioFile
if picture == nil || !strings.HasPrefix(picture.MIMEType, "image/") {
return nil, ErrNoThumbnail
}
return &Image{ContentType: picture.MIMEType, Data: picture.Data}, nil
@@ -260,7 +256,7 @@ func (j GgpDecoder) Convert(r io.Reader) (*Image, error) {
contentType := http.DetectContentType(b)
if !strings.HasPrefix(contentType, "image/") {
return nil, ErrNoConverterForExtractedImageFromGgpFile
return nil, ErrNoThumbnail
}
return &Image{ContentType: contentType, Data: b}, nil
@@ -268,12 +264,12 @@ func (j GgpDecoder) Convert(r io.Reader) (*Image, error) {
func extractBase64ImageFromGGP(ggp *GGPStruct) (string, error) {
if len(ggp.Sections) < 1 || len(ggp.Sections[0].Cards) < 1 {
return "", errors.New("cant find thumbnail in ggp file")
return "", ErrNoThumbnail
}
raw := strings.Split(ggp.Sections[0].Cards[0].Element.Image.Base64Image, "base64,")
if len(raw) < 2 {
return "", errors.New("cant decode ggp thumbnail")
return "", ErrNoThumbnail
}
return raw[1], nil
@@ -3,15 +3,17 @@ package preprocessor
import (
"archive/zip"
"bytes"
"encoding/base64"
"encoding/binary"
"io"
"os"
"strings"
"testing"
"golang.org/x/image/font"
"golang.org/x/image/font/opentype"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
@@ -77,6 +79,19 @@ var _ = Describe("preprocessor", func() {
Expect(img).To(BeNil())
})
It("reports a ggs without a thumbnail as having none", func() {
var buf bytes.Buffer
w := zip.NewWriter(&buf)
_, err := w.Create("geogebra.xml")
Expect(err).ToNot(HaveOccurred())
Expect(w.Close()).To(Succeed())
decoder := GgsDecoder{thumbnailpath: ggsThumbnailPath, maxSize: defaultMaxExtractedSize}
img, err := decoder.Convert(bytes.NewReader(buf.Bytes()))
Expect(err).To(MatchError(ErrNoThumbnail))
Expect(img).To(BeNil())
})
It("refuses an entry that expands past the limit", func() {
decoder := GgsDecoder{thumbnailpath: ggsThumbnailPath, maxSize: 1 << 20}
@@ -109,7 +124,7 @@ var _ = Describe("preprocessor", func() {
Expect(img.ContentType).To(HavePrefix("image/"))
Expect(img.Data).ToNot(BeEmpty())
})
It("should decode an audio", func() {
It("reports an audio without cover art as having none", func() {
fileContent, err := os.ReadFile("test_assets/empty_no_image.mp3")
if err != nil {
panic(err)
@@ -117,13 +132,46 @@ var _ = Describe("preprocessor", func() {
fileReader = bytes.NewReader(fileContent)
decoder := AudioDecoder{}
img, err := decoder.Convert(fileReader)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(ErrNoThumbnail))
Expect(img).To(BeNil())
})
It("should return an error if the audio is invalid", func() {
decoder := AudioDecoder{}
img, err := decoder.Convert(bytes.NewReader([]byte("not an audio")))
Expect(err).To(HaveOccurred())
Expect(err).ToNot(MatchError(ErrNoThumbnail))
Expect(img).To(BeNil())
})
})
Describe("GgpDecoder", func() {
It("hands on the embedded thumbnail", func() {
data, err := os.ReadFile("test_assets/noise.png")
Expect(err).ToNot(HaveOccurred())
ggp := `{"sections":[{"cards":[{"element":{"image":{"base64Image":"data:image/png;base64,` + base64.StdEncoding.EncodeToString(data) + `"}}}]}]}`
img, err := GgpDecoder{}.Convert(strings.NewReader(ggp))
Expect(err).ToNot(HaveOccurred())
Expect(img.ContentType).To(Equal("image/png"))
Expect(img.Data).To(Equal(data))
})
DescribeTable("reports a ggp without a thumbnail as having none",
func(ggp string) {
img, err := GgpDecoder{}.Convert(strings.NewReader(ggp))
Expect(err).To(MatchError(ErrNoThumbnail))
Expect(img).To(BeNil())
},
Entry("no sections", `{}`),
Entry("no cards", `{"sections":[{"cards":[]}]}`),
Entry("no base64 image", `{"sections":[{"cards":[{"element":{"image":{"base64Image":""}}}]}]}`),
Entry("not an image", `{"sections":[{"cards":[{"element":{"image":{"base64Image":"data:text/plain;base64,aGVsbG8="}}}]}]}`),
)
It("should return an error if the ggp is invalid", func() {
img, err := GgpDecoder{}.Convert(strings.NewReader("not a ggp"))
Expect(err).To(HaveOccurred())
Expect(err).ToNot(MatchError(ErrNoThumbnail))
Expect(img).To(BeNil())
})
})
@@ -9,7 +9,7 @@ import (
"net/http"
"net/http/httptest"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/types"