如何获取bytea的mime类型 存储在 Postgres 数据库中?
最佳答案
我知道答案有点晚了,但会帮助其他人。
正如@craig-ringer 所建议的,我已经在 plpythonu
中实现了 mime-magic,因此我可以在我的 INSERT/UPDATE-Trigger 中使用该函数。
在数据库服务器上为您的 postgresql 版本安装 plpythonu
(例如通过 apt-get
或 yum
)。不需要重新启动/重新加载数据库,因此可以轻松地在生产环境中完成。
然后在数据库服务器上安装python模块magic
:
pip install python-magic
然后在你的数据库中创建 plpythonu 语言:
CREATE LANGUAGE plpythonu;
现在你可以用 python 编写数据库函数(甚至导入 python 模块):
CREATE OR REPLACE FUNCTION mimemagic(data bytea) RETURNS TEXT AS $$
import magic
return magic.from_buffer(data, mime=True)
$$ LANGUAGE plpythonu;
如果使用 python2,postgresql 的 BYTEA
类型映射到 python 的 string
类型。
对于 python 3,它映射到 pythons bytes
类型。
创建函数后,您可以像任何其他 postgresql 函数一样在任何语句或触发器函数中使用 plpythonu 函数。 为了测试我们的功能,我们可以创建一个如下表并插入一些文件:
CREATE TABLE public.files (
file_id BIGINT PRIMARY KEY NOT NULL DEFAULT nextval('files_file_id_seq'::regclass),
name TEXT NOT NULL,
extension TEXT,
content BYTEA NOT NULL,
mime_type TEXT
);
示例查询:
SELECT name, extension, mime_type, mimemagic(content) FROM files;
结果:
name | extension | mime_type | mimemagic
----------------------------------+-----------+-----------+-----
10868_170915_1M | pdf | | application/pdf
30567_160415_1M | pdf | | application/pdf
Diode-SCS | dxf | | text/plain
Config | zip | | application/zip
btn-default-medium-focus-corners | gif | | image/gif
_loadmask | scss | | text/plain
mr | json | | text/plain
10549_160415_2M | pdf | | application/pdf
disconnect | png | | image/png
如您所见,表中未保存任何 mime_type,但会根据需要检测 mime 类型。
不用说,对每个查询的每一行执行一个函数是一个巨大的性能损失,所以 mime 类型检测应该在 INSERT/UPDATE 上完成并缓存:
示例触发器:
CREATE OR REPLACE FUNCTION files_trigger()
RETURNS TRIGGER AS $$
BEGIN
IF (TG_OP = 'INSERT') OR (TG_OP = 'UPDATE' AND new.content IS DISTINCT FROM old.content)
THEN
new.mime_type := mimemagic(new.content);
END IF;
RETURN new;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER files_insertupdate_trigger BEFORE INSERT OR UPDATE ON files
FOR EACH ROW EXECUTE PROCEDURE files_trigger();
Mime 类型现在被检测一次并保存在文件内容旁边:
SELECT name, extension, mime_type FROM files;
结果:
name | extension | mime_type
------------------------------------------+-----------+------------------------------
teamviewer_10.0.35509_amd64 | deb | application/x-debian-package
BDFE999CCC39110229563FA8C8583E239F6BDBA1 | log | text/plain
daccr-Download | exe | application/x-dosexec
为了获得更好的结果,如果可用,您还应该尝试基于文件名/-扩展名的检测,因为 mimemagic 单独对某些类型无效(json-File 被检测为文本/纯文本)。
也可以使用 magic 的选项,例如 uncompress=True
,这可能会提供更多有用的结果:
>>> import magic
>>> import mimetypes
>>> filename='verybig.json.gz'
>>> m=magic.Magic(mime=True, uncompress=False)
>>> m.from_file(filename)
'application/gzip'
>>> m=magic.Magic(mime=True, uncompress=True)
>>> m.from_file(filename)
'text/plain'
>>> mimetypes.guess_type(filename)
('application/json', 'gzip')
>>>
plpythonu 的文档可以在这里找到:http://www.postgresql.org/docs/9.5/static/plpython.html
python 的 magic 模块的代码和文档可以在这里找到:https://github.com/ahupp/python-magic
关于postgresql - 如何获取存储在 PostgreSQL 中的 bytea 的 MIME 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31445386/