<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">最近带着一对攻城狮给客户做一个web平台系统,在与客户做需求分析的过程中,发现客户有个需求痛点,那就是希望能在web上直接浏览doc文本的内容。原来的老平台在显示doc文本时,有很多问题,例如原有doc文本排版格式显示错误,例如表格位置发生了偏移,字体不再是原有doc里的字体等等。如果新系统能解决客户这一痛点,想必我们技术团队的实力会得到客户进一步的肯定。</span>
我做过调查,发现在线显示doc文本内容方法很多,一种方法是购买中间件,例如pageoffice等,这种方法缺点是中间件价格较高,客户不愿意多花费。另外方法是,先将doc转换成pdf, 将pdf转化成swf, 在客户端安装flexpaper插件,然后播放转化好的swf, 百度文库就是这么做的。第二种方法有一个很大的缺点是,用户必须自己安装flexpaper插件。但很多用户都是电脑小白,让他们动手做些操作,即使简单,但他们也会有很强的抗拒感,所以第二种方法不可行。
经过一段时间的思索,我发现可以将第二种方法简化,从而去掉手动安装插件的步骤,这样便能极大的改善用户体验了。我的做法是:doc转pdf, 然后利用mozilla开源javascript代码播放转换好的pdf,这样一来,用户将doc上传服务器后,可以通过转换后的pdf,方便的浏览上传的doc文档, 为此我在阿里云上实现了我的想法,例子如下:
在浏览器中输入:http://123.56.124.193/pdf.js/web/upload.html,会显示出doc文档上传页面:
点击 "send file" 按钮, 选择的doc文档会上传到阿里云服务器,在服务器上,我会将doc转换成pdf, 然后让浏览器将转换后的pdf显示出来:
pdf 能完美的保留doc的文档格式,显示效果跟doc完全一样,这种实现方法让客户很满意,由于我在研究的过程中学习和借鉴了很多网友的做法,这次把我的做法分享出来,和大家一起探讨。
mozilla pdf js 插件下载:
在服务区目录下执行:
git clone git://github.com/mozilla/pdf.js.git
下载后,在浏览器输入:
http://your_host_ip/pdf.js/web/viewer.html
那么一个pdf显示例子就会出来了,有关插件的详细信息可访问:
https://github.com/mozilla/pdf.js
实现细节:
1. doc 转 pdf.
doc 转 pdf 方法很多,我用的是libreoffice 的转换功能,由于我使用的是阿里云ubuntu服务器,其本身就自带了libreoffice 软件,通过libreoffice 将doc格式文件转换成pdf的命令比较简单,假设当前目录下有一个doc文档叫 1.doc, 那么将其转化为pdf 命令如下:
libreoffice --headless --invisible --convert-to pdf 1.doc
执行后,目录下会自动生成 1.pdf.
2. php 实现自动转换。
我们不可能对用户上传的每个doc文档,都手动调用上面的命令来转化,这里,我利用php来实现自动调用libreoffice 的pdf 转换命令功能,php 的exec能直接执行shell 命令,但如果在脚本中直接输入上述命令执行exec,那是会失败的。因为libreoffice 运行时,需要对HOME读取环境变量,用php执行exec,执行环境的HOME 环境变量是空,所以直接利用php调用是不行的,在php脚本代码中需要先设置HOME变量,在执行exec函数,代码如下:
<?php
function execInBackground($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd);
}
}
function convertDoc2Pdf($filename)
{
$mainFile = $filename;
$cmd2 = "export HOME=/tmp
libreoffice --headless --invisible --norestore --convert-to pdf " .
"'$mainFile'";
$saved = getenv("LD_LIBRARY_PATH"); // save old value
$newld = "/usr/lib"; // extra paths to add
if ($saved) {
putenv("LD_LIBRARY_PATH=" . $newld);
}
execInBackground($cmd2);
putenv("LD_LIBRARY_PATH=$saved");
}
?>
只要把上传的doc名字传给converDoc2Pdf, 那么服务器端就自动对上传的doc 转换成pdf.
3. 设计上传页面
上传页面很简单,就是一个上传文件的表单:
<html>
<head>
<title>Upload a doc file</title>
</head>
<body>
<h1>upload new files</h1>
<form action="upload.php" method="post" enctype="multipart/form-data"/>
<div>
<input type="hidden" name="MAX_FILE_SIZE" value="67108864" />
<label for="userfile">Upload a file:</label>
<input type="file" name="userfile" id="userfile"/>
<input type="submit" value="send File"/>
</div>
</form>
</body>
</html>
4. 上传后php的处理
当文件上传到服务器后,服务器执行upload.php, php脚本先对上传的文件作一些安全检查,并检查上传的文件是否是doc文档,如果不是,返回错误信息,如果是的话,将文件转到pdf.js/web 目录下,然后调用converDoc2Pdf函数将文本转成pdf, 接着返回一个301重定向给浏览器,浏览器根据重定向的url, 加载mozilla pdf插件,并显示转换好的pdf文档:
<html>
<head>
<title>Uploading...</title>
</head>
<body>
<h1>Uploading file<h1>
<?php
function execInBackground($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd);
}
}
function convertDoc2Pdf($filename)
{
$mainFile = $filename;
$cmd2 = "export HOME=/tmp
libreoffice --headless --invisible --norestore --convert-to pdf " .
"'$mainFile'";
$saved = getenv("LD_LIBRARY_PATH"); // save old value
$newld = "/usr/lib"; // extra paths to add
if ($saved) {
putenv("LD_LIBRARY_PATH=" . $newld);
}
execInBackground($cmd2);
putenv("LD_LIBRARY_PATH=$saved");
}
function get_extension($filename) {
return substr($filename, strrpos($filename, '.') + 1);
}
if ($_FILES['userfile']['error'] > 0)
{
echo 'Problem:';
switch ($_FILES['userfile']['error'])
{
case 1: echo 'File exceeded upload_max_filesize';
break;
// case 2: echo 'File exceeded max_file_size';
// break;
case 3: echo 'File only partially upload';
break;
case 4: echo 'No file uploaded';
break;
case 6: echo 'Cannot upload file: No temp directory specified';
break;
case 7: echo 'Upload failed: Cannot write disk';
break;
}
exit;
}
$upfile = '/var/www/html/pdf.js/web/'.$_FILES['userfile']['name'];
if (get_extension($upfile) != "doc")
{
echo "upload file is no word document<br/>";
exit;
}
if (is_uploaded_file($_FILES['userfile']['tmp_name']))
{
if (!move_uploaded_file($_FILES['userfile']['tmp_name'], $upfile))
{
echo 'Problem: Could not move file to destination directory';
exit;
}
}
else
{
echo 'Problem: Possible file upload attack. Filename: ';
echo $_FILES['userfile']['name'];
exit;
}
echo 'File uploaded successfully and begin to convert to pdf<br><br>';
convertDoc2Pdf($_FILES['userfile']['name']);
$pdfFileName = str_replace(".doc", ".pdf", $_FILES['userfile']['name']);
$redirectURL = "http://123.56.124.193/pdf.js/web/viewer.html?file=".$pdfFileName;
header("Location: ".$redirectURL, true, 301);
?>
</body>
</html>
以上就是我做的一个在线显示doc文档的小系统,系统放在阿里云服务器,大家可以用我在文中提供的url上传doc文件来体验一下。