简而言之:是否有任何PHP代码(使用ZF或其他PHP工具, 排除COM对象或其他执行文件,例如'AbiWord'; 我正在使用共享Linux服务器,没有exec
或类似功能),可以找到Word文件的页数?
编辑:即将支持的Word版本是Microsoft Word 2003和2007。
简而言之:是否有任何PHP代码(使用ZF或其他PHP工具, 排除COM对象或其他执行文件,例如'AbiWord'; 我正在使用共享Linux服务器,没有exec
或类似功能),可以找到Word文件的页数?
编辑:即将支持的Word版本是Microsoft Word 2003和2007。
获取docx文件的页数非常容易:
function get_num_pages_docx($filename)
{
$zip = new ZipArchive();
if($zip->open($filename) === true)
{
if(($index = $zip->locateName('docProps/app.xml')) !== false)
{
$data = $zip->getFromIndex($index);
$zip->close();
$xml = new SimpleXMLElement($data);
return $xml->Pages;
}
$zip->close();
}
return false;
}
对于97-2003格式来说,确定页数确实具有挑战性,但绝非不可能。页数存储在文档的SummaryInformation部分中,但由于文件的OLE格式,这使得查找变得很麻烦。结构被定义得非常彻底(尽管我认为做得不好)这里和更简单的这里。今天我花了一个小时看了这个内容,但是进展甚微!(这不是我习惯处理的抽象层次),但输出十六进制以更好地理解结构:
function get_num_pages_doc($filename)
{
$handle = fopen($filename, 'r');
$line = @fread($handle, filesize($filename));
echo '<div style="font-family: courier new;">';
$hex = bin2hex($line);
$hex_array = str_split($hex, 4);
$i = 0;
$line = 0;
$collection = '';
foreach($hex_array as $key => $string)
{
$collection .= hex_ascii($string);
$i++;
if($i == 1)
{
echo '<b>'.sprintf('%05X', $line).'0:</b> ';
}
echo strtoupper($string).' ';
if($i == 8)
{
echo ' '.$collection.' <br />'."\n";
$collection = '';
$i = 0;
$line += 1;
}
}
echo '</div>';
exit();
}
function hex_ascii($string, $html_safe = true)
{
$return = '';
$conv = array($string);
if(strlen($string) > 2)
{
$conv = str_split($string, 2);
}
foreach($conv as $string)
{
$num = hexdec($string);
$ascii = '.';
if($num > 32)
{
$ascii = unichr($num);
}
if($html_safe AND ($num == 62 OR $num == 60))
{
$return .= htmlentities($ascii);
}
else
{
$return .= $ascii;
}
}
return $return;
}
function unichr($intval)
{
return mb_convert_encoding(pack('n', $intval), 'UTF-8', 'UTF-16BE');
}
这将输出代码,其中您可以找到以下部分:
007000: 0500 5300 7500 6D00 6D00 6100 7200 7900 ..S.u.m.m.a.r.y.
007010: 4900 6E00 6600 6F00 7200 6D00 6100 7400 I.n.f.o.r.m.a.t.
007020: 6900 6F00 6E00 0000 0000 0000 0000 0000 i.o.n...........
007030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
这将允许您查看引用信息,例如:
007040: 2800 0201 FFFF FFFF FFFF FFFF FFFF FFFF (...ÿÿÿÿÿÿÿÿÿÿÿÿ
007050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
007060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
007070: 0000 0000 2500 0000 0010 0000 0000 0000 ....%...........
这将允许您确定所描述的属性:
_ab = ("SummaryInformation")
_cb = 0028
_mse = 02 (STGTY_STREAM)
_bflags = 01 (DE_BLACK)
_sidLeftSib = FFFF FFFF
_sidRightSib = FFFF FFFF (none)
_sidChild = FFFF FFFF (n/a for STGTY_STREAM)
_clsid = 0000 0000 0000 0000 0000 0000 0000 0000 (n/a)
_dwUserFlags = 0000 0000 (n/a)
_time[0] = CreateTime = 0000 0000 0000 0000 (n/a)
_time[1] = ModifyTime = 0000 0000 0000 0000 (n/a)
_startSect = 0000 0000
_ulSize = 0000 1000
_dptPropType = 0000 (n/a)
这将帮助你找到相关的代码部分,解包它并获取页面编号。当然,这是我没有时间去做的困难部分,但应该为您指明正确的方向。
微软并不让它变得容易!
DOP
)中 - 在偏移46(x2E),一个int
(2字节)中,属性名称为cPg
- 反映了最后计算的计数。因此,过程是在文件表中查找DOP,然后从该表的第42个字节中获取整数。 - OrblingOLEFile
,从中可以提取分配表,如果你能从头文件中获取目录扇区,就可以提取那个,条目为128字节。按照上面的答案格式 - "WordDocument"的起始扇区应该将您带入FIB,偏移量402是包含“Table”流中DOP位置的长整型。 - Orbling请查看来自微软codeplex的PhpWord ... "http://phpword.codeplex.com/
它可以让你在PHP中打开和读取Word格式文件,并进行任何所需处理。
要使用PHP获取doc、docx、ppt和pptx的元数据属性,例如页面数、幻灯片数,我按照以下过程进行了操作,并且它非常成功,我很高兴。下面是我遵循的过程,希望对某些人有所帮助。
Download and configure Apache Tika.
完成后,您可以尝试执行以下命令,它将提供有关文件的所有元数据。
java -jar tika-app-1.5.jar -m test.docx
java -jar tika-app-1.5.jar -m test.doc
java -jar tika-app-1.5.jar -m test.pptx
java -jar tika-app-1.5.jar -m test.ppt
除了使用Abiword或OpenOffice以外?不可能的 - 页面数量将取决于单词/字母数量、所使用的字体、对齐和字距、边距大小、行间距、段落间距、段落数量、列数、图形/嵌入式对象的大小、页面/列断点和页面边距。
您需要的是一种可以理解所有这些内容的工具。
即使您使用OpenOffice或Abiword,重新排版文本也可能会改变页面数。实际上,在某些情况下,在MSWord的不同实例中打开同一文档可能会有所不同。
您可能能够做到的最好的方法可能是基于文档表示的统计方法 - 但仍然会看到巨大的差异。
<Pages>5</Pages>
)。在2003中,我没有找到XMLs,但是可以在Windows资源管理器中查看文件属性,在摘要选项卡的高级部分中查看页面数。我现在无法测试它,但我相信这些数据不是即时计算的,而是以某种方式明确地封装在组合的Word文件中。实际上,这个数字正是我需要的。 - Yaakov Shoham