在 java 中:如何使用 mime_type 'application/octet-stream' 从二进制数据 (BYTEA) 文件中识别文件扩展名/文件类型并保存到磁盘?

Posted

技术标签:

【中文标题】在 java 中:如何使用 mime_type \'application/octet-stream\' 从二进制数据 (BYTEA) 文件中识别文件扩展名/文件类型并保存到磁盘?【英文标题】:in java: How can i identify file extension/file type from file in binary data (BYTEA) with mime_type 'application/octet-stream' and save to disk?在 java 中:如何使用 mime_type 'application/octet-stream' 从二进制数据 (BYTEA) 文件中识别文件扩展名/文件类型并保存到磁盘? 【发布时间】:2021-04-17 07:33:31 【问题描述】:

从数据库迁移中,我们在 postgreSQL 数据库中有一个数据转储。 任务是用 java 或 groovy 编写一个脚本,以便以正确的格式读出文件并将它们保存到服务器。对于某些文件,在“mime_type”列中指定了 mime_type(例如 application/pdf、image/png)。在这些情况下,我能够以正确的格式保存它们。 (-> 将它们作为字节数组输入流读入,并将它们保存为相应格式的文件)。

但 90% 的文件都有 mime_type "application/octet-stream"。在这些情况下,我怀疑文件的类型或格式是未知的。为了能够以正确的格式保存它们(例如png的pdf),我需要能够找出文件可能是什么类型。然后进行相应的转换。

我已经尝试过 URLConnection.guessContentTypeFromStream(inputStream) 方法,但这并不能识别 mime_type。

        GroovyRowResult[] fileInBinary = sql.rows("""
        SELECT * FROM table_name WHERE id = 123456
        """)


        def temp = []

        fileInBinary.each  GroovyRowResult row ->
        temp << row.data
        

        InputStream byteArrayInputStream = new ByteArrayInputStream((byte[]) temp.flatten(), temp.flatten().size())

        def mimeType = java.net.URLConnection.guessContentTypeFromStream(byteArrayInputStream)
        println "guessed mime Type is: " + mimeType

..followed by code to save the file, which works when mime_type specifies file format, e.g. pdf, word, or png

此代码有效,但guessContentType-Part 除外。

文件以二进制数据格式(BYTEA,相当于 BLOB 的 postgres)保存。

有谁知道如何找出这些应用程序/八位字节流文件最初具有的格式,从数据库中的二进制数据列(BYTEA 格式)中提取它们并将文件保存/读取到磁盘,例如pdf、docx 还是 png?

非常感谢!

【问题讨论】:

【参考方案1】:

如果您不能依赖数据库的功能,则必须使用 图书馆。 JDK 的检测特性或多或少都与 您正在使用的操作系统,因此再次使用库会提供更多 结果稳定。

这里是一个使用Apache Tika的例子:

tika.detector.detect(TikaInputStream.get(row.data), new Metadata()) 会给你mimetype。它可以直接对数据进行处理 结果集。如果您只需要检测许多 blos 上的 mimetype 和 不需要实际数据,那么考虑只读取前几个 数据块,足以检测类型。

完整示例:

@Grapes([
@Grab('org.postgresql:postgresql:+'),
@Grab('org.apache.tika:tika-core:1.25'),
])
@GrabConfig(systemClassLoader=true)
import groovy.sql.Sql
import org.apache.tika.config.TikaConfig
import org.apache.tika.io.TikaInputStream
import org.apache.tika.metadata.Metadata

def db = Sql.newInstance("jdbc:postgresql://localhost/so65682432", "postgres", "postgres")
def tika = new TikaConfig()
db.eachRow("SELECT * FROM test")  row ->
  println tika.detector.detect(TikaInputStream.get(row.image), new Metadata())

【讨论】:

非常感谢您提供快速而有用的答案! JRE 的功能可能是 File-Class 的 probeContentType 方法:docs.oracle.com/javase/7/docs/api/java/nio/file/…,正如我发现的那样。它也没有那么糟糕。

以上是关于在 java 中:如何使用 mime_type 'application/octet-stream' 从二进制数据 (BYTEA) 文件中识别文件扩展名/文件类型并保存到磁盘?的主要内容,如果未能解决你的问题,请参考以下文章

thinkphp5.1 如何判断上传的图片是个图片文件

HTML5 音频元素

如何在 BlobStore 中设置文件名属性?

PHP 7 Mime 和 PDF 验证

将mp3歌曲图像从png转换为jpg

通过理解迭代字典并获得字典[重复]