php 生成word的三種方式

原文地址 http://www.jb51.net/article/97253.htmphp

最近工做遇到關於生成word的問題css

如今總結一下生成word的三種方法。html

btw:好像只要是標題帶PHP的貌似點擊量都不是很高(哥哥我標題仍是帶上PHP了),不知道爲何,估計博客園上net技術大牛比較多吧,若是把java,.net,php比做程序員的女朋友,那麼java是Oracle門下的你們閨秀,.net微軟旗下的名門望族,PHP則是草根門下的山村野姑,這讓我等PHP草民悶騷男情何以堪情何以堪。。牢騷發完了,正式寫吧java

PHP生成word原理程序員

  • 利用windows下面的 com組件
  • 利用PHP將內容寫入doc文件之中

具體實現:算法

利用windows下面的 com組件windows

原理:com做爲PHP的一個擴展類,安裝過office的服務器會自動調用word.application的com,能夠自動生成文檔,PHP官方文檔手冊:http://www.php.net/manual/en/class.com.php緩存

使用官方實例:服務器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
// starting word
$word = new COM( "word.application" ) or die ( "Unable to instantiate Word" );
echo "Loaded Word, version {$word->Version}\n" ;
  
//bring it to front
$word ->Visible = 1;
  
//open an empty document
$word ->Documents->Add();
  
//do some weird stuff
$word ->Selection->TypeText( "This is a test..." );
$word ->Documents[1]->SaveAs( "Useless test.doc" );
  
//closing word
$word ->Quit();
  
//free the object
$word = null;
?>

我的建議:com實例後的方法都須要查找官方文檔才知道什麼意思,編輯器沒有代碼提示,很是不方便,另外這個效率也不是很高,不推薦使用app

利用PHP將內容寫入doc文件之中

這個方法又能夠分爲兩種方法

  • 生成mht格式(和HTML很類似)寫入word
  • 純HTML格式寫入word

生成mht格式(和HTML很類似)寫入word

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/**
  * 根據HTML代碼獲取word文檔內容
  * 建立一個本質爲mht的文檔,該函數會分析文件內容並從遠程下載頁面中的圖片資源
  * 該函數依賴於類MhtFileMaker
  * 該函數會分析img標籤,提取src的屬性值。可是,src的屬性值必須被引號包圍,不然不能提取
  *
  * @param string $content HTML內容
  * @param string $absolutePath 網頁的絕對路徑。若是HTML內容裏的圖片路徑爲相對路徑,那麼就須要填寫這個參數,來讓該函數自動填補成絕對路徑。這個參數最後須要以/結束
  * @param bool $isEraseLink 是否去掉HTML內容中的連接
  */
function getWordDocument( $content , $absolutePath = "" , $isEraseLink = true )
{
  $mht = new MhtFileMaker();
  if ( $isEraseLink )
   $content = preg_replace( '/<a\s*.*?\s*>(\s*.*?\s*)<\/a>/i' , '$1' , $content ); //去掉連接
  
  $images = array ();
  $files = array ();
  $matches = array ();
  //這個算法要求src後的屬性值必須使用引號括起來
  if ( preg_match_all( '/<img[.\n]*?src\s*?=\s*?[\"\'](.*?)[\"\'](.*?)\/>/i' , $content , $matches ) )
  {
   $arrPath = $matches [1];
   for ( $i =0; $i < count ( $arrPath ); $i ++)
   {
    $path = $arrPath [ $i ];
    $imgPath = trim( $path );
    if ( $imgPath != "" )
    {
     $files [] = $imgPath ;
     if ( substr ( $imgPath ,0,7) == 'http://' )
     {
      //絕對連接,不加前綴
     }
     else
     {
      $imgPath = $absolutePath . $imgPath ;
     }
     $images [] = $imgPath ;
    }
   }
  }
  $mht ->AddContents( "tmp.html" , $mht ->GetMimeType( "tmp.html" ), $content );
   
  for ( $i =0; $i < count ( $images ); $i ++)
  {
   $image = $images [ $i ];
   if ( @ fopen ( $image , 'r' ) )
   {
    $imgcontent = @ file_get_contents ( $image );
    if ( $content )
     $mht ->AddContents( $files [ $i ], $mht ->GetMimeType( $image ), $imgcontent );
   }
   else
   {
    echo "file:" . $image . " not exist!<br />" ;
   }
  }
   
  return $mht ->GetFile();
}

這個函數的主要功能其實就是分析HTML代碼中的全部圖片地址,而且依次下載下來。獲取到了圖片的內容之後,調用MhtFileMaker類,將圖片添加到mht文件中。具體的添加細節,封裝在MhtFileMaker類中了。

使用方法:遠程調用

?
1
2
3
4
5
6
7
8
url= http: //www.***.com;
  
$content = file_get_contents ( $url );
  
$fileContent = getWordDocument( $content , "http://www.jb51.net/Music/etc/" );
$fp = fopen ( "test.doc" , 'w' );
fwrite( $fp , $fileContent );
fclose( $fp );

其中,$content變量應該是HTML源代碼,後面的連接應該是能填補HTML代碼中圖片相對路徑的URL地址

本地生成調用:

?
1
2
3
4
5
6
7
8
header( "Cache-Control: no-cache, must-revalidate" );
header( "Pragma: no-cache" );
$wordStr = 'http://www.jb51.net/' ;
$fileContent = getWordDocument( $wordStr );
$fileName = iconv( "utf-8" , "GBK" , ‘jb51 ' . ' _ '. $intro . ' _' . rand(100, 999));
header( "Content-Type: application/doc" );
header( "Content-Disposition: attachment; filename=" . $fileName . ".doc" );
echo $fileContent ;

注意,在使用這個函數以前,您須要先包含類MhtFileMaker,這個類能夠幫助咱們生成Mht文檔。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
<?php
/***********************************************************************
Class:  Mht File Maker
Version:  1.2 beta
Date:   02/11/2007
Author:  Wudi
Description: The class can make .mht file.
***********************************************************************/
  
class MhtFileMaker{
  var $config = array ();
  var $headers = array ();
  var $headers_exists = array ();
  var $files = array ();
  var $boundary ;
  var $dir_base ;
  var $page_first ;
  
  function MhtFile( $config = array ()){
  
  }
  
  function SetHeader( $header ){
   $this ->headers[] = $header ;
   $key = strtolower ( substr ( $header , 0, strpos ( $header , ':' )));
   $this ->headers_exists[ $key ] = TRUE;
  }
  
  function SetFrom( $from ){
   $this ->SetHeader( "From: $from" );
  }
  
  function SetSubject( $subject ){
   $this ->SetHeader( "Subject: $subject" );
  }
  
  function SetDate( $date = NULL, $istimestamp = FALSE){
   if ( $date == NULL) {
    $date = time();
   }
   if ( $istimestamp == TRUE) {
    $date = date ( 'D, d M Y H:i:s O' , $date );
   }
   $this ->SetHeader( "Date: $date" );
  }
  
  function SetBoundary( $boundary = NULL){
   if ( $boundary == NULL) {
    $this ->boundary = '--' . strtoupper (md5(mt_rand())) . '_MULTIPART_MIXED' ;
   } else {
    $this ->boundary = $boundary ;
   }
  }
  
  function SetBaseDir( $dir ){
   $this ->dir_base = str_replace ( "\\" , "/" , realpath ( $dir ));
  }
  
  function SetFirstPage( $filename ){
   $this ->page_first = str_replace ( "\\" , "/" , realpath ( "{$this->dir_base}/$filename" ));
  }
  
  function AutoAddFiles(){
   if (!isset( $this ->page_first)) {
    exit ( 'Not set the first page.' );
   }
   $filepath = str_replace ( $this ->dir_base, '' , $this ->page_first);
   $filepath = 'http://mhtfile' . $filepath ;
   $this ->AddFile( $this ->page_first, $filepath , NULL);
   $this ->AddDir( $this ->dir_base);
  }
  
  function AddDir( $dir ){
   $handle_dir = opendir( $dir );
   while ( $filename = readdir( $handle_dir )) {
    if (( $filename != '.' ) && ( $filename != '..' ) && ( "$dir/$filename" != $this ->page_first)) {
     if ( is_dir ( "$dir/$filename" )) {
      $this ->AddDir( "$dir/$filename" );
     } elseif ( is_file ( "$dir/$filename" )) {
      $filepath = str_replace ( $this ->dir_base, '' , "$dir/$filename" );
      $filepath = 'http://mhtfile' . $filepath ;
      $this ->AddFile( "$dir/$filename" , $filepath , NULL);
     }
    }
   }
   closedir ( $handle_dir );
  }
  
  function AddFile( $filename , $filepath = NULL, $encoding = NULL){
   if ( $filepath == NULL) {
    $filepath = $filename ;
   }
   $mimetype = $this ->GetMimeType( $filename );
   $filecont = file_get_contents ( $filename );
   $this ->AddContents( $filepath , $mimetype , $filecont , $encoding );
  }
  
  function AddContents( $filepath , $mimetype , $filecont , $encoding = NULL){
   if ( $encoding == NULL) {
    $filecont = chunk_split ( base64_encode ( $filecont ), 76);
    $encoding = 'base64' ;
   }
   $this ->files[] = array ( 'filepath' => $filepath ,
         'mimetype' => $mimetype ,
         'filecont' => $filecont ,
         'encoding' => $encoding );
  }
  
  function CheckHeaders(){
   if (! array_key_exists ( 'date' , $this ->headers_exists)) {
    $this ->SetDate(NULL, TRUE);
   }
   if ( $this ->boundary == NULL) {
    $this ->SetBoundary();
   }
  }
  
  function CheckFiles(){
   if ( count ( $this ->files) == 0) {
    return FALSE;
   } else {
    return TRUE;
   }
  }
  
  function GetFile(){
   $this ->CheckHeaders();
   if (! $this ->CheckFiles()) {
    exit ( 'No file was added.' );
   }
   $contents = implode( "\r\n" , $this ->headers);
   $contents .= "\r\n" ;
   $contents .= "MIME-Version: 1.0\r\n" ;
   $contents .= "Content-Type: multipart/related;\r\n" ;
   $contents .= "\tboundary=\"{$this->boundary}\";\r\n" ;
   $contents .= "\ttype=\"" . $this ->files[0][ 'mimetype' ] . "\"\r\n" ;
   $contents .= "X-MimeOLE: Produced By Mht File Maker v1.0 beta\r\n" ;
   $contents .= "\r\n" ;
   $contents .= "This is a multi-part message in MIME format.\r\n" ;
   $contents .= "\r\n" ;
   foreach ( $this ->files as $file ) {
    $contents .= "--{$this->boundary}\r\n" ;
    $contents .= "Content-Type: $file[mimetype]\r\n" ;
    $contents .= "Content-Transfer-Encoding: $file[encoding]\r\n" ;
    $contents .= "Content-Location: $file[filepath]\r\n" ;
    $contents .= "\r\n" ;
    $contents .= $file [ 'filecont' ];
    $contents .= "\r\n" ;
   }
   $contents .= "--{$this->boundary}--\r\n" ;
   return $contents ;
  }
  
  function MakeFile( $filename ){
   $contents = $this ->GetFile();
   $fp = fopen ( $filename , 'w' );
   fwrite( $fp , $contents );
   fclose( $fp );
  }
  
  function GetMimeType( $filename ){
   $pathinfo = pathinfo ( $filename );
   switch ( $pathinfo [ 'extension' ]) {
    case 'htm' : $mimetype = 'text/html' ; break ;
    case 'html' : $mimetype = 'text/html' ; break ;
    case 'txt' : $mimetype = 'text/plain' ; break ;
    case 'cgi' : $mimetype = 'text/plain' ; break ;
    case 'php' : $mimetype = 'text/plain' ; break ;
    case 'css' : $mimetype = 'text/css' ; break ;
    case 'jpg' : $mimetype = 'image/jpeg' ; break ;
    case 'jpeg' : $mimetype = 'image/jpeg' ; break ;
    case 'jpe' : $mimetype = 'image/jpeg' ; break ;
    case 'gif' : $mimetype = 'image/gif' ; break ;
    case 'png' : $mimetype = 'image/png' ; break ;
    default : $mimetype = 'application/octet-stream' ; break ;
   }
   return $mimetype ;
  }
}
?>

點評:這種方法的缺點是不支持批量生成下載,由於一個頁面只能有一個header,(不管遠程使用仍是本地生成聲明header頁面只能輸出一個header),即便你循環生成,結果仍是隻有一個word生成(固然你能夠修改上面的方式來實現)

2.純HTML格式寫入word

原理:

利用ob_start把html頁面先存儲起來(解決一下頁面多個header問題,能夠批量生成),而後在寫入doc文檔內容利用

代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
class word
{
function start()
{
ob_start();
echo '<html xmlns:o= "urn:schemas-microsoft-com:office:office"
xmlns:w= "urn:schemas-microsoft-com:office:word"
}
function save( $path )
{
  
echo "</html>" ;
$data = ob_get_contents();
ob_end_clean();
  
$this ->wirtefile ( $path , $data );
}
  
function wirtefile ( $fn , $data )
{
$fp = fopen ( $fn , "wb" );
fwrite( $fp , $data );
fclose( $fp );
}
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$html = '
<table width=600 cellpadding= "6" cellspacing= "1" bgcolor= "#336699" >
<tr bgcolor= "White" >
  <td>PHP10086</td>
  <td><a href= "http://www.php10086.com" target= "_blank" >http://www.php10086.com</a></td>
</tr>
<tr bgcolor= "red" >
  <td>PHP10086</td>
  <td><a href= "http://www.php10086.com" target= "_blank" >http://www.php10086.com</a></td>
</tr>
<tr bgcolor= "White" >
  <td colspan=2 >
  PHP10086<br>
  最靠譜的PHP技術博客分享網站
  </td>
</tr>
</table>
';
  
//批量生成
for ( $i =1; $i <=3; $i ++){
  $word = new word();
  $word ->start();
  //$html = "aaa".$i;
  $wordname = 'PHP淮北的我的網站--PHP10086.com' . $i . ".doc" ;
  echo $html ;
  $word ->save( $wordname );
  ob_flush(); //每次執行前刷新緩存
  flush ();
}

我的點評:這種方法效果最好,緣由有兩個:

第一代碼比較簡潔,很容易理解,第二種支持批量生成word(這個很重要)

第三支持完整的html代碼

生成了三個word文檔:而且內容支持完整的html代碼顯示,第三種方法強烈推薦

相關文章
相關標籤/搜索