From 605d52a86e114570598989c85d8e2ec87221ec24 Mon Sep 17 00:00:00 2001 From: guqing <38999863+guqing@users.noreply.github.com> Date: Thu, 10 Oct 2024 15:45:00 +0800 Subject: [PATCH] refactor: optimize file type detection and support decision-making based on file name (#6675) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### What type of PR is this? /kind improvement /area core /milestone 2.20.x #### What this PR does / why we need it: 优化文件类型检测并支持根据文件名作为决策依据 #### Does this PR introduce a user-facing change? ```release-note 优化文件类型检测并支持根据文件名作为决策依据 ``` --- .../app/infra/utils/FileTypeDetectUtils.java | 41 ++++++++++--- .../LocalAttachmentUploadHandler.java | 6 +- .../infra/utils/FileTypeDetectUtilsTest.java | 55 ++++++++++++++++++ .../resources/file-type-detect/index.html | 0 .../test/resources/file-type-detect/index.js | 0 .../resources/file-type-detect/other.xlsx | Bin 0 -> 9031 bytes .../test/resources/file-type-detect/test.docx | Bin 0 -> 10251 bytes .../test/resources/file-type-detect/test.json | 0 .../test/resources/file-type-detect/test.png | Bin 0 -> 17156 bytes .../test/resources/file-type-detect/test.svg | 1 + 10 files changed, 91 insertions(+), 12 deletions(-) create mode 100644 application/src/test/resources/file-type-detect/index.html create mode 100644 application/src/test/resources/file-type-detect/index.js create mode 100644 application/src/test/resources/file-type-detect/other.xlsx create mode 100644 application/src/test/resources/file-type-detect/test.docx create mode 100644 application/src/test/resources/file-type-detect/test.json create mode 100644 application/src/test/resources/file-type-detect/test.png create mode 100644 application/src/test/resources/file-type-detect/test.svg diff --git a/api/src/main/java/run/halo/app/infra/utils/FileTypeDetectUtils.java b/api/src/main/java/run/halo/app/infra/utils/FileTypeDetectUtils.java index f9326863e..7166260d4 100644 --- a/api/src/main/java/run/halo/app/infra/utils/FileTypeDetectUtils.java +++ b/api/src/main/java/run/halo/app/infra/utils/FileTypeDetectUtils.java @@ -1,29 +1,52 @@ package run.halo.app.infra.utils; +import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import lombok.experimental.UtilityClass; -import org.apache.tika.Tika; +import org.apache.tika.detect.DefaultDetector; +import org.apache.tika.detect.Detector; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.metadata.TikaCoreProperties; import org.apache.tika.mime.MimeTypeException; import org.apache.tika.mime.MimeTypes; +import org.springframework.util.Assert; @UtilityClass public class FileTypeDetectUtils { - private static final Tika tika = new Tika(); + private static final Detector detector = new DefaultDetector(); + + /** + *

Detects the media type of the given document.

+ *

The type detection is based on the content of the given document stream and the name of + * the document.

+ * + * @param inputStream the document stream must not be null + * @throws IOException if the stream can not be read + */ + public static String detectMimeType(InputStream inputStream, String name) throws IOException { + Assert.notNull(name, "The name of the document must not be null"); + var metadata = new Metadata(); + metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, name); + return doDetectMimeType(inputStream, metadata); + } /** * Detect mime type. * - * @param inputStream input stream will be closed after detection. + * @param inputStream input stream will be closed after detection, must not be null */ public static String detectMimeType(InputStream inputStream) throws IOException { - try { - return tika.detect(inputStream); - } finally { - if (inputStream != null) { - inputStream.close(); - } + return doDetectMimeType(inputStream, new Metadata()); + } + + private static String doDetectMimeType(InputStream inputStream, Metadata metadata) + throws IOException { + Assert.notNull(inputStream, "The inputStream must not be null"); + try (var stream = (!inputStream.markSupported() + ? new BufferedInputStream(inputStream) : inputStream)) { + return detector.detect(stream, metadata).toString(); } } diff --git a/application/src/main/java/run/halo/app/core/attachment/endpoint/LocalAttachmentUploadHandler.java b/application/src/main/java/run/halo/app/core/attachment/endpoint/LocalAttachmentUploadHandler.java index bb48574d4..2c4351112 100644 --- a/application/src/main/java/run/halo/app/core/attachment/endpoint/LocalAttachmentUploadHandler.java +++ b/application/src/main/java/run/halo/app/core/attachment/endpoint/LocalAttachmentUploadHandler.java @@ -158,7 +158,7 @@ class LocalAttachmentUploadHandler implements AttachmentHandler { var typeValidator = file.content() .next() .handle((dataBuffer, sink) -> { - var mimeType = detectMimeType(dataBuffer.asInputStream()); + var mimeType = detectMimeType(dataBuffer.asInputStream(), file.name()); var isAllow = setting.getAllowedFileTypes() .stream() .map(FileCategoryMatcher::of) @@ -178,9 +178,9 @@ class LocalAttachmentUploadHandler implements AttachmentHandler { } @NonNull - private String detectMimeType(InputStream inputStream) { + private String detectMimeType(InputStream inputStream, String name) { try { - return FileTypeDetectUtils.detectMimeType(inputStream); + return FileTypeDetectUtils.detectMimeType(inputStream, name); } catch (IOException e) { log.warn("Failed to detect file type", e); return "Unknown"; diff --git a/application/src/test/java/run/halo/app/infra/utils/FileTypeDetectUtilsTest.java b/application/src/test/java/run/halo/app/infra/utils/FileTypeDetectUtilsTest.java index a69ee0c80..1c3e407d0 100644 --- a/application/src/test/java/run/halo/app/infra/utils/FileTypeDetectUtilsTest.java +++ b/application/src/test/java/run/halo/app/infra/utils/FileTypeDetectUtilsTest.java @@ -3,6 +3,7 @@ package run.halo.app.infra.utils; import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; +import java.io.InputStream; import java.nio.file.Files; import org.apache.tika.mime.MimeTypeException; import org.junit.jupiter.api.Test; @@ -31,6 +32,60 @@ class FileTypeDetectUtilsTest { assertThat(mimeType).isEqualTo("application/zip"); } + @Test + void detectMimeTypeWithNameTest() throws IOException { + var stream = getFileInputStream("classpath:file-type-detect/index.js"); + String mimeType = FileTypeDetectUtils.detectMimeType(stream, "index.js"); + assertThat(mimeType).isEqualTo("application/javascript"); + + stream = getFileInputStream("classpath:file-type-detect/index.html"); + mimeType = + FileTypeDetectUtils.detectMimeType(stream, "index.html"); + assertThat(mimeType).isEqualTo("text/html"); + + stream = getFileInputStream("classpath:file-type-detect/test.json"); + mimeType = FileTypeDetectUtils.detectMimeType(stream, "test.json"); + assertThat(mimeType).isEqualTo("application/json"); + + stream = getFileInputStream("classpath:file-type-detect/other.xlsx"); + mimeType = FileTypeDetectUtils.detectMimeType(stream, "other.xlsx"); + assertThat(mimeType).isEqualTo( + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + + // other.xlsx detect without name + stream = getFileInputStream("classpath:file-type-detect/other.xlsx"); + mimeType = FileTypeDetectUtils.detectMimeType(stream); + assertThat(mimeType).isEqualTo("application/zip"); + + // other.xlsx detect with wrong name + stream = getFileInputStream("classpath:file-type-detect/other.xlsx"); + mimeType = FileTypeDetectUtils.detectMimeType(stream, "other.txt"); + assertThat(mimeType).isEqualTo("application/zip"); + + stream = getFileInputStream("classpath:file-type-detect/test.docx"); + mimeType = FileTypeDetectUtils.detectMimeType(stream, "test.docx"); + assertThat(mimeType).isEqualTo( + "application/vnd.openxmlformats-officedocument.wordprocessingml.document"); + + // docx detect without file name + stream = getFileInputStream("classpath:file-type-detect/test.docx"); + mimeType = FileTypeDetectUtils.detectMimeType(stream); + assertThat(mimeType).isEqualTo("application/zip"); + + stream = getFileInputStream("classpath:file-type-detect/test.svg"); + mimeType = FileTypeDetectUtils.detectMimeType(stream, "test.svg"); + assertThat(mimeType).isEqualTo("image/svg+xml"); + + stream = getFileInputStream("classpath:file-type-detect/test.png"); + mimeType = FileTypeDetectUtils.detectMimeType(stream, "test.png"); + assertThat(mimeType).isEqualTo("image/png"); + } + + private static InputStream getFileInputStream(String location) throws IOException { + var file = ResourceUtils.getFile(location); + return Files.newInputStream(file.toPath()); + } + @Test void detectFileExtensionTest() throws MimeTypeException { var ext = FileTypeDetectUtils.detectFileExtension("application/x-x509-key; format=pem"); diff --git a/application/src/test/resources/file-type-detect/index.html b/application/src/test/resources/file-type-detect/index.html new file mode 100644 index 000000000..e69de29bb diff --git a/application/src/test/resources/file-type-detect/index.js b/application/src/test/resources/file-type-detect/index.js new file mode 100644 index 000000000..e69de29bb diff --git a/application/src/test/resources/file-type-detect/other.xlsx b/application/src/test/resources/file-type-detect/other.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..1d2b9647f0751884f7af4eee065d5d3cfd8b6daf GIT binary patch literal 9031 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 literal 0 HcmV?d00001 diff --git a/application/src/test/resources/file-type-detect/test.json b/application/src/test/resources/file-type-detect/test.json new file mode 100644 index 000000000..e69de29bb diff --git a/application/src/test/resources/file-type-detect/test.png b/application/src/test/resources/file-type-detect/test.png new file mode 100644 index 0000000000000000000000000000000000000000..820549a92cc43233d73e8cdbe4683f3c5be07ee3 GIT binary patch literal 17156 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 literal 0 HcmV?d00001 diff --git a/application/src/test/resources/file-type-detect/test.svg b/application/src/test/resources/file-type-detect/test.svg new file mode 100644 index 000000000..e93f41998 --- /dev/null +++ b/application/src/test/resources/file-type-detect/test.svg @@ -0,0 +1 @@ + \ No newline at end of file