php 7.2 finfo 魔术文件

Posted

技术标签:

【中文标题】php 7.2 finfo 魔术文件【英文标题】:php 7.2 finfo magic file 【发布时间】:2019-03-29 12:28:55 【问题描述】:

我有一个 Laravel 5 项目,让用户下载 .ai(插图文件)。问题是 Laravel 将 .ai 文件检测为 application/pdf。

我正在使用此功能检测 mime 类型

$type = File::mimeType( $_path );

我也尝试过使用这种方法,但得到了相同的结果

$finfo = finfo_open(FILEINFO_MIME);
$mimetype = $finfo->file($_path);
finfo_close($finfo);

我想,这一定是 php 不知道 .ai 文件是什么的问题。我深入研究了 finfo,我知道默认的 mime 定义被编译到 PHP 中,但我看到 finfo_open 有第二个参数“magic_file”,我认为这是一个可以插入不同 mime 定义文件的路径的地方.

我尝试使用 Ubuntu 的 /etc/magic.mime 文件,但 finfo 给了我

ErrorException: finfo_open(): Warning: offset `application\/activemessage' invalid in

错误。我认为这是因为 magic.mime 文件格式不正确。

网上的大多数主题都创建了一个自定义 PHP 函数或其他一些 hack 来检测 mime 类型,但我觉得这不是正确的解决方案。

在哪里可以找到最新的 mime 定义文件以及如何将它们加载到 PHP 或 finfo 中?

我的环境:

Ubuntu 16.04
PHP 7.2

【问题讨论】:

【参考方案1】:

我想,这一定是 PHP 的问题,根本不知道什么是 .ai 文件是。我深入研究了 finfo 并且我明白默认 mime 定义被编译成 PHP,但我看到 finfo_open,有 第二个参数'magic_file',我认为这是一个你可以 插入不同的 mime 定义文件的路径。

fileinfo extension 尝试通过在文件中的特定位置查找某些 magic 序列来猜测 mime 类型。魔术文件是一个数据库,存储了与已知魔术序列一样多的数据库。

我有一个 Laravel 5 项目,让用户下载 .ai (插图文件)。问题是 Laravel 将 .ai 文件检测为 申请/pdf。

按照上面的解释,查找魔术文件以将.ai文件检测为pdf是可以的。因为Adobe Illustrator Artwork是一个可以保存为EPS或PDF格式的文件。

我做了一些研究,很难区分普通的pdf文件和以pdf格式保存的ai文件。首先,我从网上下载了免费的ai文件,用hexdumpfile两个命令查看magic number来识别文件。

$ hexdump -C 7_full_ai_vi_template_vector_8.ai | head
00000000  25 50 44 46 2d 31 2e 34  0d 25 e2 e3 cf d3 0d 0a  |%PDF-1.4.%......|
00000010  31 20 30 20 6f 62 6a 0d  3c 3c 20 0d 2f 54 79 70  |1 0 obj.<< ./Typ|
00000020  65 20 2f 43 61 74 61 6c  6f 67 20 0d 2f 50 61 67  |e /Catalog ./Pag|
00000030  65 73 20 32 20 30 20 52  20 0d 2f 4d 65 74 61 64  |es 2 0 R ./Metad|
00000040  61 74 61 20 38 38 20 30  20 52 20 0d 3e 3e 20 0d  |ata 88 0 R .>> .|
00000050  65 6e 64 6f 62 6a 0d 32  20 30 20 6f 62 6a 0d 3c  |endobj.2 0 obj.<|
00000060  3c 20 0d 2f 54 79 70 65  20 2f 50 61 67 65 73 20  |< ./Type /Pages |
00000070  0d 2f 4b 69 64 73 20 5b  20 35 20 30 20 52 20 5d  |./Kids [ 5 0 R ]|
00000080  20 0d 2f 43 6f 75 6e 74  20 31 20 0d 3e 3e 20 0d  | ./Count 1 .>> .|
00000090  65 6e 64 6f 62 6a 0d 33  20 30 20 6f 62 6a 0d 3c  |endobj.3 0 obj.<|
$ file 7_full_ai_vi_template_vector_8.ai
7_full_ai_vi_template_vector_8.ai: PDF document, version 1.4

查看文件的前几个字节,如您所见,它是带有.ai 扩展名的PDF 文件。

之后,我在 Mac 上使用 Preview 打开它,它知道这个文件是由 Adob​​e Illustrator 在 Inspector Dialog 中创建的。所以它必须有某种方法来找出保存为 PDF 格式的 AI 文件。

大多数在线主题创建自定义PHP函数或其他一些 hack 来检测 mime 类型,但我觉得这不是正确的 解决方案在这里。

在哪里可以找到最新的 mime 定义文件以及如何加载 将它们转换成 PHP 或 finfo?

我在谷歌上搜索了没有运气的解决方案,所以我自己创建了它,在Adobe Illustrator File Format Specification 的第 15 页中,它说:

%%Creator 注释标识生成 PostScript 语言文档。版本号(版本 6.0 在 图 1) 是任意文本,以换行符结尾。

我假设文件开头包含 pdf 魔术字节和字符串 %%Creator Adobe Illustrator 的文件应标识为 .ai

让我们写一些magic rule:

$ cat ai
0       string          %PDF-           PDF document
!:mime  application/pdf
>5      byte            x               \b, version %c
>7      byte            x               \b.%c
>7      search/1000     %%Creator:\ Adobe\ Illustrator  Adobe Illustrator Document

PHP 脚本使用 .ai 的自定义魔法文件

$ cat fileinfo.php
<?php

$magic_file = __DIR__ . '/ai';

$finfo = new finfo(FILEINFO_NONE, $magic_file);
echo $finfo->file($argv[1]) . PHP_EOL;

会输出

$ php fileinfo.php ./7_full_ai_vi_template_vector_8.ai
PDF document, version 1.4 Adobe Illustrator Document

它有效,但我认为维护自己的魔法文件不是一个好主意。也许你可以为它写一个简单的函数,在$type = File::mimeType( $_path );说它是pdf文件之后检测.ai

【讨论】:

以上是关于php 7.2 finfo 魔术文件的主要内容,如果未能解决你的问题,请参考以下文章

PHP - finfo_file 返回错误的 MIME 类型

从php中的文件名获取mime类型

获取文件mime类型

php文件下载指向链接

PHP的魔术常量和魔术方法

PHP魔术方法和魔术常量