如何从没有扩展名且MIME类型为octet-stream的文件中提取文件扩展名?

3

我有许多文件,它们的原始文件名已被数据库中的 ID 替换。例如,曾经的文件名为 word_document.doc 现在变成了 12345。在此过程中,我丢失了原始文件名。

现在我想要提供这些文件下载。用户应该能够下载文件并使用其原始应用程序查看文件。这些文件均为以下格式之一:

  • .txt(文本)
  • .doc(Word 文档)
  • .docx(Word 文档)
  • .wpd(Word Perfect)
  • .pdf(PDF)
  • .rtf(富文本)
  • .sxw(Star Office)
  • .odt(Open Office)

我正在使用

$fhandle = finfo_open(FILEINFO_MIME);
$file_mime_type = finfo_file($fhandle, $filepath);

获取mime类型,然后将mime类型映射到扩展名。

我遇到的问题是一些文件的mime类型为 octet-stream 。我在网上阅读了一些资料,这种类型似乎是二进制文件的杂项类型。我无法轻易地确定需要什么扩展名。在某些情况下,将其设置为 .wpd 可以工作,在某些情况下则不行。同样适用于 .sxw


@degr 我确实将文件名保存在数据库中,但用户被允许“删除”他们的文件。 “删除”只是从数据库中删除保存文件名等信息的行。作为网站的一部分,我们需要保留这些文件,并使它们仍然可以访问,因为这些文件现在归其他人所有。 - Caleb Doucet
@Caleb Doucet 你需要从数据库中删除带有行的文件。如果你需要保留文件,也可以在数据库中保留行,只需添加一个名为“deleted”的“bit”字段即可。 - degr
@degr 我理解解决方案是保留数据库记录,但这需要大量的重新工作(因为这是一个大系统)。预算不允许你提出的建议。 - Caleb Doucet
此外,当您生成新的文件名与数据库中的匹配行时,您还可以在文件附近保留一些元数据。例如,您有文件12341和数据库中ID为12341的行。您可以这样做:file_put_contents(12341.' .metadata',serialize(database->getRowById(12341)))。这很丑陋,但完美地工作。 - degr
很遗憾,我不知道其他的解决方案。 - degr
显示剩余2条评论
1个回答

2
"

Symfony2 3步完成

1)mime_content_type

"
$type = mime_content_type($path);

// remove charset (added as of PHP 5.3)
if (false !== $pos = strpos($type, ';')) {
    $type = substr($type, 0, $pos);
}

return $type;

2) file -b --mime

ob_start();
passthru(sprintf('file -b --mime %s 2>/dev/null', escapeshellarg($path)), $return);
if ($return > 0) {
    ob_end_clean();

    return;
}

$type = trim(ob_get_clean());
if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) {
    // it's not a type, but an error message
    return;
}

return $match[1];

3) finfo

if (!$finfo = new \finfo(FILEINFO_MIME_TYPE, $path)) {
    return;
}

return $finfo->file($path);

获取到 MIME 类型后,你可以从预定义的映射表中获取扩展名,例如在 这里 或者 这里
$map = array(
    'application/msword' => 'doc',
    'application/x-msword' => 'doc',
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
    'application/pdf' => 'pdf',
    'application/x-pdf' => 'pdf',
    'application/rtf' => 'rtf',
    'text/rtf' => 'rtf',
    'application/vnd.sun.xml.writer' => 'sxw',
    'application/vnd.oasis.opendocument.text' => 'odt',
    'text/plain' => 'txt',
);

这些是获取文件路径的MIME类型的好方法,但我已经检索到了MIME类型。我需要知道如何将八位流MIME类型解析为适当的扩展名。 - Caleb Doucet
好的,我认为没有一种100%的确定扩展名的方法,但将这3种方法结合起来应该能做得很好。有时候自动化95%比什么都不做要好。剩下的5%可以手动处理。他们有相同的扩展名的可能性非常大:) - Nikita U.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接