php压缩/解压zip的利器-PclZip
PclZip简介与使用
PclZip介绍
PclZip library能够压缩与解压缩Zip格式的压缩档(WinZip、PKZIP);且能对此类类档案进行处理,包括产生压缩档、列出压缩档的内容以及解压缩档案等等。由于能够在伺服器端进行压缩与解压缩的动作,所以相当方便使用。
PclZip定义一个PclZip类别,其类别物件可视为一个ZIP档案,亦提供method来进行处理。
如何使用PclZip
1.基础
所有的功能都由pclzip.lib.php这个档案提供,PclZip library可于其首页(www.phpconcept.net/pclzip/index.en.php)下载。所有的PKZIP档案其实就是一个PclZip的类别物件。当产生一个PclZip档案(ie, PclZip类别物件),就会先产生一个压缩档,且档名已经指定,但此压缩档的内容尚未存在:
< ?PHP
require_once('pclzip.lib.php');
$archive = new PclZip("archive.zip");
?>
此物件提供了一些public method可用来处理此档案。
2.参数
每一个method有其各自可使用的参数,包括有必须与非必须的参数:
< ?PHP
require_once('pclzip.lib.php');
$archive = new PclZip('archive.zip');
$v_list = $archive->add('dev/file.txt',
PCLZIP_OPT_REMOVE_PATH, 'dev');
?>
上例中的’dev/file.txt’就是必须参数;’PCLZIP_OPT_REMOVE_PATH’则为非必须参数。当然有些method也可以只包含非必须的参数:
< ?PHP $list = $archive->extract(PCLZIP_OPT_PATH, "folder", PCLZIP_OPT_REMOVE_PATH, "data", PCLZIP_CB_PRE_EXTRACT, "callback_pre_extract",); ?>
上例中原本压缩档内档案存放的路径为/data,不过你可以指定解压缩至/folder中。此外,在解压缩之前,会呼叫callback function(’callback_pre_extract()’),此function可让使用者在解压缩的过程中变更档案存放路径与档名,或是选择某些档案不解压缩。
所有可用的非必要参数可参考网址(www.phpconcept.net/pclzip/man/en/index.php)。
3.回传值
每个method所回传的值可能会不同,将会在每个method中说明。不过大部分的method回传0、error或是阵列。
4.错误处理
从版本1.3之后,错误处理已经整合至PclZip类别中,当一个method回传错误码,可以得知一些额外的讯息以方便错误处理:
* errorName():回传错误名称
* errorCode():回传错误码
* errorInfo():回传错误的描述
接下来会举几个例子来说明如何使用PclZip。
PclZip实例1、产生ZIP压缩档
PclZip($zipname):为PclZip constructor,$zipname为PKZIP压缩档的档名。
主要是产生一个PclZip物件,即一个PKZIP压缩档;但此时,只有压缩档产生出来,并做一些检查(例如是否有开启zlib extension…等),除此之外,并没有做其他动作。
create($filelist, [optional arguments list]):将参数$filelist指定的档案或目录(包含当中所有档案与子目录)加入上述所产生的压缩档中。
而非必要的参数则能够修改压缩档内的档案存放路径。
此method可用的参数可以参考网志(www.phpconcept.net/pclzip/man/en/index.php)。
下面的示例说明如何产生PKZIP压缩档(档名为archive.zip),并将file.txt、data/text.txt以及目录folder(包含当中的档案与子目录)加入刚刚产生的archive.zip中:
< ?PHP
include_once('pclzip.lib.php');
$archive = new PclZip('archive.zip');
$v_list = $archive->create('file.txt,data/text.txt,folder');
if ($v_list == 0) {
die("Error : ".$archive->errorInfo(true));
}
?>
下面的示例说明基本上与上例一样产生archive.zip,但在将file.txt与text.txt压缩于其中时,将路径由data/改为install/ ;因此,在archive.zip中这两个档案的路径会是install/file.txt与install/text.txt
< ?PHP
include_once('pclzip.lib.php');
$archive = new PclZip('archive.zip');
$v_list = $archive->create('data/file.txt,data/text.txt',
PCLZIP_OPT_REMOVE_PATH, 'data',
PCLZIP_OPT_ADD_PATH, 'install');
if ($v_list == 0) {
die("Error : ".$archive->errorInfo(true));
}
?>
PclZip实例2、列出压缩档内容
listContent( ) :列出压缩档中的内容,包括档案的属性与目录:
< ?PHP
include_once('pclzip.lib.php');
$zip = new PclZip("test.zip");
if (($list = $zip->listContent()) == 0) {
die("Error : ".$zip->errorInfo(true));
}
for ($i=0; $i<sizeof ($list); $i++) {
for(reset($list[$i]); $key = key($list[$i]); next($list[$i])) {
echo "File $i / [$key] = ".$list[$i][$key]."<br>";
}
echo "<br />";
}
?></sizeof>
上例将会回传结果:
File 0 / [filename] = data/file1.txt
File 0 / [stored_filename] = data/file1.txt
File 0 / [size] = 53
File 0 / [compressed_size] = 36
File 0 / [mtime] = 1010440428
File 0 / [comment] =
File 0 / [folder] = 0
File 0 / [index] = 0
File 0 / [status] = ok
File 1 / [filename] = data/file2.txt
File 1 / [stored_filename] = data/file2.txt
File 1 / [size] = 54
File 1 / [compressed_size] = 53
File 1 / [mtime] = 1011197724
File 1 / [comment] =
File 1 / [folder] = 0
File 1 / [index] = 1
File 1 / [status] = ok
PclZip实例3、解压缩档案
extract([options list]) :解压缩PKZIP中的档案或目录。
[options list]可用的参数可参考网址(www.phpconcept.net/pclzip/man/en/index.php)。这些参数能让使用者在解压缩的时候有更多的选项,譬如指定变更解压缩档案的路径、指定只解压缩某些档案或不解压缩某些档案或者是将档案解压缩成字串输出(可用于readme档)。
下例是一个简单的解压缩档案示例,将压缩档archive.zip内的档案解压缩至目前的目录:
< ?PHP
require_once('pclzip.lib.php');
$archive = new PclZip('archive.zip');
if ($archive->extract() == 0) {
die("Error : ".$archive->errorInfo(true));
}
?>
下例是进阶的解压缩档案使用,archive.zip中所有档案都解压缩于data/中,而特别指明在install/release中的所有档案也直接丢于data/中,而非data/install/ release:
< ?PHP
include('pclzip.lib.php');
$archive = new PclZip('archive.zip');
if ($archive->extract(PCLZIP_OPT_PATH, 'data',
PCLZIP_OPT_REMOVE_PATH, 'install/release') == 0) {
die("Error : ".$archive->errorInfo(true));
}
?>
本文转自 http://www.ccvita.com/59.html
spring2.5+struts2+hibernate3.6 整合心得
配置log4j属性文件
在tomcat启动的时候,出现这个警告:
log4j:WARN No appenders could be found for logger (org.apache.commons.digester.Digester.sax).
log4j:WARN Please initialize the log4j system properly.
解决办法:
log4j.properties文件需要放到web-inf/class目录下面,在eclipse里面放到src目录下面,会自动拷贝到class目录下面去。
文件:log4j.properties
log4j.rootLogger=CONSOLE,FILE
log4j.addivity.org.apache=true
# 应用于控制台
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=INFO
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.Encoding=GBK
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
# 每天新建日志
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File=C:/log4j/log
log4j.appender.A1.Encoding=GBK
log4j.appender.A1.Threshold=DEBUG
log4j.appender.A1.DatePattern='.'yyyy-MM-dd
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L : %m%n
#应用于文件
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=C:/log4j/file.log
log4j.appender.FILE.Append=false
log4j.appender.FILE.Encoding=GBK
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
# 应用于文件回滚
log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE.Threshold=ERROR
log4j.appender.ROLLING_FILE.File=rolling.log
log4j.appender.ROLLING_FILE.Append=true
log4j.appender.CONSOLE_FILE.Encoding=GBK
log4j.appender.ROLLING_FILE.MaxFileSize=10KB
log4j.appender.ROLLING_FILE.MaxBackupIndex=1
log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
#自定义Appender
log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender
log4j.appender.im.host = mail.cybercorlin.net
log4j.appender.im.username = username
log4j.appender.im.password = password
log4j.appender.im.recipient = yyflyons@163.com
log4j.appender.im.layout=org.apache.log4j.PatternLayout
log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
#应用于socket
log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
log4j.appender.SOCKET.RemoteHost=localhost
log4j.appender.SOCKET.Port=5001
log4j.appender.SOCKET.LocationInfo=true
# Set up for Log Facter 5
log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n
# Log Factor 5 Appender
log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000
# 发送日志给邮件
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
log4j.appender.MAIL.Threshold=FATAL
log4j.appender.MAIL.BufferSize=10
log4j.appender.MAIL.From=yyflyons@163.com
log4j.appender.MAIL.SMTPHost=www.wusetu.com
log4j.appender.MAIL.Subject=Log4J Message
log4j.appender.MAIL.To=yyflyons@126.com
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
Spring配置文件
需要注意xml文件的头部
开启对注解和事务的支持需要加语句
<context:annotation-config />
<tx:annotation-driven/>
文件:applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <!-- 打开依赖注解方式注入 --> <context:annotation-config /> <!-- 配置数据源 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost/ssh"/> <property name="username" value="root"/> <property name="password" value="5476"/> </bean> <!-- 配置sessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mappingResources"> <list> <value>com/test/bean/user.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> <!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref local="sessionFactory" /> </property> </bean> <!-- 配置事务拦截器Bean --> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <!-- 为事务拦截器bean注入一个事物管理器 --> <property name="transactionManager" ref="transactionManager"></property> <property name="transactionAttributes"> <!-- 定义事务传播属性 --> <props> <prop key="insert*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="add*">PROPAGATION_REQUIRED</prop> <prop key="remove*">PROPAGATION_REQUIRED</prop> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="change*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> <!-- 打开事务支持 --> <tx:annotation-driven transaction-manager="transactionManager"/> <!--<import resource=""/>--> <bean id="userService" class="com.test.service.impl.UserServiceBean" /> <bean id="userAction" class="com.test.action.UserAction"> <property name="userService" ref="userService"/> </bean></beans>
Spring 需要的jar包
asm-2.2.3.jar
asm-commons-2.2.3.jar
asm-util-2.2.3.jar
aspectjrt.jar
aspectjweaver.jar
cglib-nodep-2.1_3.jar
common-annotations.jar
commons-dbcp.jar
commons-logging.jar
commons-pool.jar
log4j-1.2.15.jar
spring.jar
spring-webmvc-struts.jar //支持struts2
Struts2配置文件
最重要的一句
<!– 把action对象交给spring创建 –>
<constant value=”spring” />
文件:Struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <!-- 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 --> <constant name="struts.i18n.encoding" value="UTF-8" /> <!-- 设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 --> <constant name="struts.serve.static.browserCache" value="false" /> <!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 --> <constant name="struts.configuration.xml.reload" value="true" /> <!-- 开发模式下使用,这样可以打印出更详细的错误信息 --> <constant name="struts.devMode" value="true" /> <!-- 默认的视图主题 --> <constant name="struts.ui.theme" value="simple" /> <!-- 最关键的参数 --> <!-- 把action对象交给spring创建 --> <constant name="struts.objectFactory" value="spring" /> <package name="myDefault" extends="struts-default"> <default-action-ref name="indexPage" /> <global-results> <result name="exceptionPage">/exceptionPage.jsp</result> </global-results> <global-exception-mappings> <exception-mapping result="exceptionPage" exception="java.lang.Exception" /> </global-exception-mappings> <action name="indexPage"> <result>/index.jsp</result> </action> </package> <package name="user" namespace="/user" extends="myDefault"> <!-- 这里面的class不是指完整类路径,而是指在spring中定义的bean的名称 --> <action name="userAction" class="userAction"> <result name="success">/success.jsp</result> <result name="input">/index.jsp</result> </action> </package> </struts>
Struts需要的jar包
commons-beanutils-1.7.0.jar
commons-chain-1.2.jar
commons-fileupload-1.2.1.jar
commons-io-1.3.2.jar
commons-logging-1.0.4.jar
commons-logging-api-1.1.jar
commons-validator-1.3.1.jar
freemarker-2.3.15.jar
ognl-2.7.3.jar
oro-2.0.8.jar
struts2-core-2.1.8.jar
struts2-spring-plugin-2.1.8.jar
tiles-api-2.0.6.jar
tiles-core-2.0.6.jar
tiles-jsp-2.0.6.jar
xwork-core-2.1.6.jar
Hibernate的配置
Hibernate需要的jar包
antlr-2.7.6.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
ehcache-1.5.0.jar
hibernate3.jar
hibernate-jpa-2.0-api-1.0.0.Final.jar
javassist-3.12.0.GA.jar
jta-1.1.jar
slf4j-api-1.6.1.jar
slf4j-log4j12-1.6.1.jar
文件:user.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.test.bean"> <class name="User" table="user"> <id name="id"> <generator class="native"/> </id> <property name="name" length="10" not-null="true"/> <property name="password" length="10" not-null="true"/> </class> </hibernate-mapping>
Myeclipse8.0/8.5丢失配置和默认workspace问题
修改Myeclipse根目录下的configuration/config.ini文件
osgi.instance.area.default=file:\D\:\\projects\\myeclipse
完美解决
php 生成日历的简单程序
<?php
$month = $_GET['m']?$_GET['m']:date(‘n’);
$year = $_GET['y']?$_GET['y']:date(‘Y’);
$start_week = date(‘w’,mktime(0,0,0,$month,1,$year));
$day_num = date(‘t’,mktime(0,0,0,$month,1,$year));
$end = false;
?>
<table>
<tr>
<td>星期日</td><td>星期一</td><td>星期二</td><td>星期三</td><td>星期四</td><td>星期五</td><td>星期六</td>
</tr>
<tr>
<?php
for($i = 0; $i<$start_week; $i++)
{
echo “<td></td>”;
}
$j=1;
while($j<=$day_num)
{
echo “<td>$j</td>”;
$week = ($start_week+$j-1)%7;
if($week ==6){
echo “\n\t</tr>\n”;
if($j != $day_num)
echo “\t<tr>\n\t\t”;
else $end = true;
}
$j++;
}
while($week%7 != 6)
{
echo “<td></td>”;
$week++;
}
if(!$end)
echo “\n</tr>”;
?>
</table>
javascript 表单 submit()错误
做个简单的表单验证,调用表单对象的submit对象竟然出现submit is not a function这样的错误,花了半个晚上的时间,终于找出了原因
原来 js对submit关键字敏感,而我的表单中有按钮name=”submit”…
把所有的name=”submit”去掉一切正常
吐血。。。
纯javascript 单行向上滚动效果代码
<style>
*{margin:0;padding:0;}
#scrollDiv {height:30px;overflow:hidden;position:relative;margin:50px;}
#scrollUl {position:absolute;}
#scrollUl li{height:30px;line-height:30px;}
</style>
<script type="text/javascript">
function scrollOneStep(obj)
{
var ul = document.getElementById(obj);
var li = ul.getElementsByTagName("li");
var li_move = li.item(0);
var line = 0 - parseInt(li_move.clientHeight);
var speed = 10;
var pix = 0;
t2 = setInterval(function(){
if(pix > line){
ul.style.top = ""+pix + "px";
pix --;
}else{
clearInterval(t2);
}
},speed);
ul.style.top += parseInt(ul.style.top)+30+"px";
ul.removeChild(li_move);
ul.appendChild(li_move);
ul.style.top = "0"
}
function scroll(obj)
{
var t= setInterval(function(){scrollOneStep(obj);},1000);
}
</script>
<div id="scrollDiv">
<ul id="scrollUl">
<li>164101***400</li>
<li>334205***400</li>
<li>164101***400</li>
<li>334205***400</li>
<li>164101***400</li>
<li>334205***400</li>
<li>164101***400</li>
</ul>
</div>
<script language="javascript"> scroll('scrollUl'); </script>
smarty 函数插件里使用组合变量(变量连接)
针对函数传递的变量连接问题:
<?PHP
$var['name'] = ‘shooting’;
?>
我想要在smarty中实现这样的效果:
{fck name = “var[shooting]“}
错误的写法:
{fck name = “var[$var.name]“}
这样$var.name就被解析成了Array.name显然是错误的
正确的写法:
{fck name = “var[`$var.name`]“}
“`”这个符号,是键盘左上角,数字1前面的那个符号
在php中使用 TCPDF 动态创建 PDF [转载]
TCPDF 是托管在 Sourceforge.net 上最活跃的项目之一,其完全在 PHP 上实现了强大的 PDF 生成引擎。这使得其更容易安装,即使在您无法访问系统目录或编译自己的代码的站点上。同时,通过让您直接查看 PHP 代码生成的结果,而不使用任何中间步骤,这使迭代开发更加容易。
TCPDF 支持一系列有用的图像格式,包括 SVG 矢量格式和位图格式,如 JPEG 和 PNG。一个简单独立的实用工具让您可以处理 TrueType、OpenType、PostScript Type 1 和 CID-0 字体,使它们可以添加到 TCPDF 创建的文档。您可以使用 TCPDF 来生成无数 1-D 和 2-D 条形码格式,且它支持所有常见的 PDF 功能,如书签、文档链接、压缩、注释、文档加密和数字签名。
用 PHP 编写 TCPDF 并使用其页面,这使其易于创建并部署 PDF 生成的 Web 页面。在您使用任何支持 Web 服务器和您最喜欢的 PHP 开发环境开发并部署 TCPDF 时,我将使用如下工具:
- Eclipse V3.5.2 — 我最新欢的开源开发环境之一,其支持广泛的编程语言和环境。
- PHP Development Tools V2.2.0 — 适用于 Eclipse 的 PHP 插件。
- MAMP Pro V1.9 — 适用于 Mac OS X 的方便的程序包,其通过有用的 GUI 前端在一个隔离的环境中提供 Apache、MySQL 和 PHP。虽然 Mac OS X 附带安装 Apache 和 PHP,但我还是选择使用此工具,因为其提供了一系列稳定且容易分离的 Web 服务器/数据库/PHP。
- TCPDF V5.0.006 — TCPDF 当前的稳定版本。
您可以在 参考资料 部分找到以上所有工具的下载链接。
如果您已经安装了 PHP,我们就来看看如何在您自己的网站上使用 TCPDF。我们将检查安装过程,然后我们将使用 PHP 生成一个显示可能来自任何电子商务站点的发票式样(invoice-style)文档的网页。此后,我们将使用 TCPDF 来创建一个使用类似格式的可打印的 PDF 版发票。
当您从 Sourceforge.net 下载 TCPDF 时,它提供一个自包含的 ZIP 存档,也就是说,您可以使用您最喜欢的 ZIP 提取工具来解压存档,您最终将获得一个包含您所需要的所有信息的 TCPDF 目录。
如果您将 TCPDF 目录添加到您的 web 文档目录,则您可以通过加载 doc/index.html 访问 TCPDF 文档并通过加载 examples/index.php 文件查看任何示例,这也可在 TCPDF 网站上找到(请参考 参考资料)。
然而在您可以查看示例以前,您需要配置您的 TCPDF 安装。
如果您正在类 UNIX® 系统上安装 TCPDF,则您需要更改文件模式,因为它们并没有全部被标记为可执行。在 Microsoft® Windows® 系统上存在一个创建 TCPDF 存档的副作用。幸运的是,很容易在来自 shell 的一个失衡中调整这些(请参考 清单 1)。您还需要确保缓存和图像目录是可写入的,因为 TCPDF 将在那里存储临时文件。
下一步,您需要将文件分配给用户和组 web 服务器;虽然这通常是用户 www 和组 www,但是这将取决于您的系统。如果您正在您的个人网站领域以外运行 TCPDF,(在您的主目录下通常是 public_html),则您可以跳过此步骤。
清单 1. 调整文件模式和所有权
$ cd tcpdf $ find . -type f | xargs chmod -x $ chmod +w cache images $ chown -R www:www . |
请注意命令可能使用 . 代替 : 来在一些系统上分离用户和组;如果出现问题,则检查其文档详细资料。
使用您最喜欢的文本编辑器,加载 config/tcpdf_config.php 文件。这就是 TCPDF 的配置设置并让您控制库的默认设置,并告诉它如何找到自己的支持文件。
在 tcpdf_config.php 中您想要变更的设置包括:
PDF_PAGE_FORMAT— 如果您不使用公制页面格式,则设置其为letter。除非您手头有一些非常奇特方法,否则 TCPDF 可能比您的打印机支持更大的页面尺寸。PDF_UNIT— 如果您想用点而不是毫米来布置您的 PDF 文档,则设置其为pt。PDF_CREATOR、PDF_AUTHOR— 一旦您的 PDF 生成代码忘了设置它们,则默认文档创建者和作者。
您可以在您的 PHP 代码中调整这些设置中的任意一个,如果无法确定也无需担心(例如,如果您在此处设置的是像模式文档布局,您仍然可以创建景观文档)。
假设您没有移动文件和目录远离其初始位置,则通过默认配置设置,TCPDF 应该没有呈现任何其附带示例的问题。
在这一点上,您可以加载示例文件以确保您拥有一个正在运行的 TCPDF 安装。让我们使用它来创建一个可打印版的发票。
在您创建了电子商务网站以后,您的客户将订购一些物品,而您将收取他们的货款。虽然这很不错,但是他们将想得到某种发票,以防订单错误或他们的信用卡公司搞混了付款,。
让我们制作一个合理美观的发票网页,这样他们可以看到他们已经订购了什么和您将要向他们收取什么。
使用我最喜欢的 PHP 开发环境,我已经创建了一个新的发票文件夹,其包含如下文件:
- Invoice.php — PHP 生成发票
- Invoice.css — CSS 式样的发票
- Azuresol_OnyxTree-S.png — Azuresol 的 “OnyxTree S”,您将其用作您公司的标志(来自 iconfinder.com Web 站点的免费图标(请参考 参考资料))
- gentleface_print.png — gentleface 的 “Print”,您将使用其触发 PDF 生成(来自 iconfinder.com 的另一个免费图标)
在 Invoice.php 内部,检查看看是否使用 PDF 参数调用页面(请参考 清单 2)。如果不是,用户想要一个正常 web 页面,这样您就可以使用 generateHTML 函数(请参考 清单 3)显示页面。稍后您将看到 generatePDF 函数,但是可以肯定使用它来生成发票数据的 PDF 没任何问题。
Listing 2. 页面生成控制代码
if( array_key_exists( 'PDF', $_REQUEST ) ) {
generatePDF( $invoiceData );
} else {
generateHTML( $invoiceData );
}
|
$invoiceData 阵列拥有所有发票数据;虽然您将直接在 Invoice.php 上创建它,但是您可以设想数据来自于数据库、web 服务或某种网上购物车系统。
清单 3. 生成 HTML
function generateHTML( $data ) {
?>
... HTML code was here ...
<?php
foreach( $data['items'] as $item ) {
echo '<tr>' . "\n";
echo ' <td>' . $item[0] . "</td>\n";
echo ' <td>' . $item[1] . "</td>\n";
echo ' <td>' . $item[2] . "</td>\n";
echo ' <td>' . $item[3]. "</td>\n";
echo "</tr>\n";
}
?>
... HTML code was here ...
<?php
echo '<td>' . $data['total'] . "</td>\n";
?>
... HTML code was here ...
<?php
echo 'Invoice prepared for ' . $data['user'] . ' on ' . $data['date'] . "\n";
?>
... HTML code was here ...
<?php
}
|
为了简单明了我已经删掉了此处所有的 HTML 标记代码;您可以在位于 CreatingPDFs-Invoice.zip 存档文件中的 Invoice.php 上看到它, CreatingPDFs-Invoice.zip 存档文件可以在 下载 部分找到。
使用传递给函数的发票信息作为 $data,创建一个包含每个项目一行的表、及其数量、单价和总价的表。在表的末尾,添加一个包含订单的总成本的行。页脚包含用户 ID 和发票生成的日期/时间。
当然,简单明了的事情,以及您在自己站点上实现它的时候所面临的主要挑战,将与您的数据源互动,并获得恰到好处的 CSS 式样。
图 1. 光彩夺目的网页发票

我完全虚构了一家提供优良咖啡和茶的 South Seas Pacifica 公司,显然我对 Sumatran 品种深深的吸引了。至少他们的价格很吸引人!
右下角的打印机图标是诱人的,您希望能够有单击那里并获得打印发票。这里就是 TCPDF 的用武之地。并不只是打印网页,您将为我们尊贵的客户提供一个时髦的 PDF 版本,这会使他们在轻松的状态下完成打印。
现在,您的网页发票看起来很好,您需要创建可以打印的 PDF 版本。
回忆 清单 2,将 PDF 参数 (http://…/Invoice.php?PDF) 与 Invoice.php 页面一起加载将调用具有相同数据的 generatePDF 函数(请参考清单 4)。
清单 4. 生成 PDF 发票
function generatePDF( $data ) {
# Create a new PDF document.
$pdf = new InvoicePdf( $data, 'P', 'pt', 'LETTER' );
# Generate the invoice.
$pdf->CreateInvoice();
# Output the PDF document.
$pdf->Output( 'Your_Invoice.pdf', 'D' );
}
|
generatePDF 函数创建了一个 InvoicePdf 对象,调用其 CreateInvoice 方法,然后发送一个名为 Your_Invoice.pdf 的下载 PDF 文档给用户的浏览器。虽然这看起来非常简单,但是隐藏了必须自己创建 InvoicePdf 类的事实,且需要复制原始发票式样。让我们来看看这是如何进行的。
InvoicePdf 类扩展了 TCPDF 的 TCPDF 类,这是主 PDF 生成引擎。在构造函数(请参考 清单 5)中,使用传入的 $orientation(页面方向)、$unit(计量单位)和 $format(页 面大小)初始化父类。TCPDF 构造函数的最后三个参数表明输入的是 Unicode(默认为 Ture),已生成 PDF 的字符编码格式是 UTF-8,且您不应使用磁盘缓存 (False)。虽然在创建 PDF 时,磁盘缓存减少了内存占用,但是速度变得更慢了。因为我们的文件不大也不复杂,所以无需权衡这一点。
在初始化父类以后,将参考存储到发票数据以便今后使用。下一步,使用 SetMargins 方法将页边距设置为宽度 72 点、高度 36 点。SetMargins 最终参数表明您正在用自己的值来重写默认页边距。使用 SetAutoPageBreaks 方法,可在从底部算起有 36 点高时告知 TCPDF 自动创建新页面。
清单 5. InvoicePdf 类构造函数
function __construct( $data, $orientation, $unit, $format ) {
parent::__construct( $orientation, $unit, $format, true, 'UTF-8', false );
$this->invoiceData = $data;
# Set the page margins: 72pt on each side, 36pt on top/bottom.
$this->SetMargins( 72, 36, 72, true );
$this->SetAutoPageBreak( true, 36 );
# Set document meta-information
$this->SetCreator( PDF_CREATOR );
$this->SetAuthor( 'Chris Herborth (chrish@pobox.com)' );
$this->SetTitle( 'Invoice for ' . $this->invoiceData['user'] );
$this->SetSubject( "A simple invoice example for 'Creating PDFs on
the fly with TCPDF' on IBM's developerWorks" );
$this->SetKeywords( 'PHP, sample, invoice, PDF, TCPDF' );
//set image scale factor
$this->setImageScale(PDF_IMAGE_SCALE_RATIO);
//set some language-dependent strings
global $l;
$this->setLanguageArray($l);
}
|
在建立边距以后,设置 PDF 文档元信息。这将显示在您最喜欢的 PDF 查看器中的文档属性窗口。这些仅仅是字符串,因此您可以将它们设置为任何对您的应用程序有意义的信息。
使用 setImageScale 方法,在 TCPDF 的配置文件中使用默认图像缩放比例设置。这是用于将位图图像的大小从像素大小调整为适合的页面。
最后,使用 setLanguageArray 来为 PDF 文件设置一些语言相关的字符串;通过 TCPDF 主配置,这些会在特定语言配置文件中定义。
在 清单 6 中,您重写了 Header 方法,其被调用以便生成每一个页面的标题内容。首先,定义一些变量。以 14 点的 bigFont 大小开始,您会计算出商标图像的相对大小和相对于 bigFont 大小的正常文本大小。然后您将深入 TCPDF 调用。
ImagePngAlpha 方法插入放置在其左上角宽 72 点、高 32 点的商标图像,其与您以前的边距设置相匹配。因为它是一个正方形的图像,所以您可以指定相同的宽度和高度(已计算的 $imageScale)。您将要说明它是一个 PNG 图像,因为此调用实际可以插入 PNG 和 JPEG 图像(如果在您的 PHP 安装中已安装了 GD 库,则其也可以加载任何由 GD 支持的图像)。下一步,指定一个空值,因为您没有为此图像添加 PDF 链接(通过 AddLink 方法创建)目标。再下一步,使用 T 来说明您想在图像区域的右上角制定下一个 PDF 对象。最后,告知 TCPDF 不要调整图像大小,既保持初始的 72 dpi(一个通用的屏幕分辨率),且图像在页面上应该左对齐。
显然,ImagePngAlpha 方法对如何在 PDF 文档中将图像添加到页面的问题上给予您大量的控制(请参考清单 6)。
清单 6. 页面标题的生成
public function Header() {
global $webcolor;
# The image is this much larger than the company name text.
$bigFont = 14;
$imageScale = ( 128.0 / 26.0 ) * $bigFont;
$smallFont = ( 16.0 / 26.0 ) * $bigFont;
$this->ImagePngAlpha('Azuresol_OnyxTree-S.png', 72, 36, $imageScale,
$imageScale, 'PNG', null, 'T', false, 72, 'L' );
$this->SetFont('times', 'b', $bigFont );
$this->Cell( 0, 0, 'South Seas Pacifica', 0, 1 );
$this->SetFont('times', 'i', $smallFont );
$this->Cell( $imageScale );
$this->Cell( 0, 0, '', 0, 1 );
$this->Cell( $imageScale );
$this->Cell( 0, 0, '31337 Docks Avenue,', 0, 1 );
$this->Cell( $imageScale );
$this->Cell( 0, 0, 'Toronto, Ontario', 0, 1 );
$this->SetY( 1.5 * 72, true );
$this->SetLineStyle( array( 'width' => 2, 'color' =>
array( $webcolor['black'] ) ) );
$this->Line( 72, 36 + $imageScale, $this->getPageWidth() - 72, 36
+ $imageScale );
}
|
在标题上放置商标图像以后,设置字体(粗体 Times,使用您的 bigFont 大小),然后创建一些单元格来存放公司的名称和地址信息。这些单元格在 HTML 上包含文本,而且有点像表格单元格。Cell 方法采用这些参数(实际上更多;参考 TCPDF 文档获取完整列表):
Width— 单元格宽度;如果设置为 0,则单元格一直扩展到右侧边距(或者如果您使用的是从右到左的语言,则扩展到左侧边距)。Height— 单元格高度;如果设置为 0,则单元格高度将扩展,以便能放得下内容。Text— 该文本在单元格内绘制,使用当前的字体和颜色设置。Border— 说明是否边界应该根据单元格制定。在这种情况下,由于您正在使用 0,所以您无需任何边界。您也可以传递 1 来根据单元格制定完整的边界,或字符串以便说明特定的边界。Position— 说明何处创建下一个单元格;1 表明您需要其在下一行的开始出显示,但是您可以使用 0 在此单元格旁边添加下一个单元格,或者 2 以停留在当前的 X 坐标并移到下一行。
最后,我们的 Header 方法在标题的底部绘制了一条两点黑线,一直穿过页面的内容区域。图 2 显示了将如何在页面上查看,如 Mac OS X 的 预览应用程序所呈现的那样。
图 2. 打印标题,就像网页标题

现在您已经创建了一个原始标题的合理副本,您也需要重写 Footer 方法,以便于您生成页脚。这非常简单,只包含用户 ID 和发票信息,其通过另外一个两点黑线从剩余的页面中分离出来。
您尚未看到此方法的唯一部分正在使用使用一个负值调用 SetY 方法。在您这样做的时候,相对于页面的底部设置当前的 Y。在这里,您将要为页面页脚留下大量的空间,以确保您的绘制不太接近底部边距(请参考清单 7)。
清单 7. 页面页脚的生成
public function Footer() {
global $webcolor;
$this->SetLineStyle( array( 'width' => 2, 'color' =>
array( $webcolor['black'] ) ) );
$this->Line( 72, $this->getPageHeight() - 1.5 * 72 - 2,
$this->getPageWidth() - 72, $this->getPageHeight() - 1.5 * 72 - 2 );
$this->SetFont( 'times', '', 8 );
$this->SetY( -1.5 * 72, true );
$this->Cell( 72, 0, 'Invoice prepared for ' .
$this->invoiceData['user'] . ' on ' . $this->invoiceData['date'] );
}
|
在您创建页面时,显示出来的就像发票的网络版,只是减去了打印机的图标。您已经中断了此操作,因为这是打印版本(它是多余的)。图 3 得出了结果。
图 3. 已打印的页脚

在这一点上,您拥有附带美观的页眉和页脚的空白页。您需要为此添加实际的发票内容,这样做很有用。
在使用 AddPage 方法启动新的页面以后(在这种情况下,这是唯一的页面),将字体设置为 11 点 Helvetica 并将插入点从页面的顶部移动到 144 点处。在表开始以前,这会在页眉以下给我们留出一个小空间。
下一步,要计算您将需要使表居中的缩进量,这基于页面宽度、两个 72 点边距、一个宽列和三个正常列。
在此之后,您将使用以前计算出的值并描绘出每个单元格的完全边界,来创建一系列单元格以呈现列标题。您还要右对齐数字列的标题因为它们通过值进行排列。在标题单元格的最后,您要调用 Ln 方法以便向下移动到下一行的开始。
通过在发票上迭代项目的 foreach 循环,您为每一个内容行进行同类型的布局(请参考清单 8)。
清单 8. 页面内容的生成
public function CreateInvoice() {
$this->AddPage();
$this->SetFont( 'helvetica', '', 11 );
$this->SetY( 144, true );
# Table parameters
#
# Column size, wide (description) column, table indent, row height.
$col = 72;
$wideCol = 3 * $col;
$indent = ( $this->getPageWidth() - 2 * 72 - $wideCol - 3 * $col ) / 2;
$line = 18;
# Table header
$this->SetFont( '', 'b' );
$this->Cell( $indent );
$this->Cell( $wideCol, $line, 'Item', 1, 0, 'L' );
$this->Cell( $col, $line, 'Quantity', 1, 0, 'R' );
$this->Cell( $col, $line, 'Price', 1, 0, 'R' );
$this->Cell( $col, $line, 'Cost', 1, 0, 'R' );
$this->Ln();
# Table content rows
$this->SetFont( '', '' );
foreach( $this->invoiceData['items'] as $item ) {
$this->Cell( $indent );
$this->Cell( $wideCol, $line, $item[0], 1, 0, 'L' );
$this->Cell( $col, $line, $item[1], 1, 0, 'R' );
$this->Cell( $col, $line, $item[2], 1, 0, 'R' );
$this->Cell( $col, $line, $item[3], 1, 0, 'R' );
$this->Ln();
}
# Table Total row
$this->SetFont( '', 'b' );
$this->Cell( $indent );
$this->Cell( $wideCol + $col * 2, $line, 'Total:', 1, 0, 'R' );
$this->SetFont( '', '' );
$this->Cell( $col, $line, $this->invoiceData['total'], 1, 0, 'R' );
}
|
代码的最后一位呈现总行数。这演示了您如何可以更容易地在单元格之间变更字体式样(通过调用 SetFont 方法来打开或关闭粗体)。第一个文本单元格的宽度被设置横跨表的前三列,因为您需要发票总数出现在最后一列的底部。
一旦您完成后,发票项目表看起来将非常的棒(请参考图 4)。
图 4. 发票上的项目

通过逻辑地布局文本单元格,您已经用适合打印的格式重新创建了初始的网页。在无需变更网页本身或任何基础数据的情况下,TCPDF 让您将创建 PDF 的支持添加到您现存的 PHP 网页上。
本文向您介绍了 TCPDF,它是一种用于生成 PDF 文档的流行 PHP 库。TCPDF 无需额外的库就能执行此操作,并使其作为您现有 PHP 网站的一部分易于安装。本文向您显示了在类 UNIX 系统中安装并配置 TCPDF 的概述。然后您创建了一个简单的基于 Web 的发票,类似于您可能在一家从事异国热饮的电子商务站点上所看到的诸如此类的事情。
一旦您拥有一个看上去像专业发票的网页,您就可以扩展 TCPDF 类来生产一个 PDF 版本的发票,即客户可以轻松地下载或打印。重写 Header 和 Footer 方法让我们用相似的方式建立页面,然后您可以编写一个附加方法来布置发票项目作为一个表。
| 描述 | 名字 | 大小 | 下载方法 |
|---|---|---|---|
| 文章源代码 | os-tcpdf-CreatingPDFs-Invoice.zip | 21KB | HTTP |
本文转载自IBM.COM
http://www.ibm.com/developerworks/cn/opensource/os-tcpdf/index.html?ca=drs-
ajax 返回的innerHTML里面的javascript代码执行问题及Demo [转载]
解决了一个困扰我许久的问题,用过AJAX的人可能会知道,当把从服务器返回xhr.responseText的数据设定给innerHTML时, 里面的JS代码并不能够执行,查了很多资料,终于找到一个简单而且可行的办法,就是把JS代码封装到一个DIV中通过xhr.responseText打 包给innerHTML,然后把<script></script>标签扒下去,在通过eval()函数执行JS代码(思想转载 自这 里),这里以弹出对话框为例,示例如下:
<!–这是innerHTML的内容–>
<div id=”a”>
<script>
alert(“aa”);
<script>
</div>
<!–这是调用JS的主页内容–>
var pageInfo = xhr.responseText;
document.getElementById(“pageInfo”).innerHTML = pageInfo;
eval(document.getElementById(“aa”).innerHTML.replace(/<script>|<\/script>/,”)); //将<script>标签替换掉,这样才能被eval()函数执行
结果出现了显示”aa”的对话框!
但是问题又出现了,如果执行2句或者两句以上的JS代码就会出现错误了!
这样我们就可以把需要执行的多行JS代码封装成一个方法直接放到需要调用该JS代码的主页面里,然后再被调用的页面里写上这个方法名就可以了,这里 以弹出2个对话框为例,示例如下:
<!–这是innerHTML的内容–>
<div id=”a”>
<script>
doit();
<script>
</div>
<!–这是调用JS的主页内容–>
var pageInfo = xhr.responseText;
document.getElementById(“pageInfo”).innerHTML = pageInfo;
eval(document.getElementById(“aa”).innerHTML.replace(/<script>|<\/script>/,”)); //将<script>标签替换掉,这样才能被eval()
function doit(){
alert(“aa”);
alert(“bb”);
}
结果出现了”aa” “bb”两个对话框!
这样就完美解决了ajax 返回的innerHTML里面的javascript代码执行问题,一些复杂的JS函数都可以,而且一些jQuery的方法也可以哦!
这是在网上找的资料,依据以此,我写了例子来 验证:
Defalut.aspx
<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”Default.aspx.cs” Inherits=”AjaxJsTestWeb._Default” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head runat=”server”>
<title>无标题页</title>
<script language=”javascript” type=”text/javascript” >
function getRequest() {
http_request = false;
if (window.XMLHttpRequest) {
//对于Mozilla﹑Netscape﹑Safari等浏览器,创建XMLHttpRequest
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
//如果服务器响应的header不是text/xml,可以调用其它方法修改该header
http_request.overrideMimeType(‘text/xml’);
}
} else if (window.ActiveXObject) {
// 对于Internet Explorer浏览器,创建XMLHttpRequest
try {
http_request = new ActiveXObject(“Msxml2.XMLHTTP”);
} catch (e) {
try {
http_request = new ActiveXObject(“Microsoft.XMLHTTP”);
} catch (e) {}
}
}
return http_request;
}
//获得Url 的responseText
function getResponseText(url)
{
http_request=getRequest();
http_request.open(‘GET’, url, false);
http_request.send(null);
if (http_request.readyState == 4)
{
// 收到完整的服务器响应
if (http_request.status == 200) {
//HTTP服务器响应的值OK
requestdoc = http_request.responseText;
//将服务器返回的字符串写到页面中ID为message的区域
}
else {
requestdoc = http_request.status;
}
}
return requestdoc;
}
//获得Url 的responseXML
//代码片段
function getResponseXml(url)
{
http_request=getRequest();
http_request.open(‘GET’, url, false);
http_request.send(null);
if (http_request.readyState == 4)
{
// 收到完整的服务器响应
if (http_request.status == 200) {
//HTTP服务器响应的值OK
requestdoc = http_request.responseXML;
//将服务器返回的字符串写到页面中ID为message的区域
}
else {
requestdoc = http_request.status;
}
}
return requestdoc;
}
function TestAjaxJs()
{
http_request=getRequest();
http_request.open(‘GET’, “containjsText.aspx”, false);
http_request.send(null);
if (http_request.readyState == 4)
{
// 收到完整的服务器响应
if (http_request.status == 200) {
//HTTP服务器响应的值OK
requestdoc = http_request.responseText;
//将服务器返回的字符串写到页面中ID为message的区域
}
else {
requestdoc = http_request.status;
}
}
// debugger;
document.getElementById(“divJsText”).InnerHTML=requestdoc;
alert( document.getElementById(“divJsText”).InnerHTML);
var str;
str=document.getElementById(“divJsText”).InnerHTML.replace(/<script language=’javascript’>|<\/script>/,”);
str=str.replace(/<\/script>/,”);
alert(str);
eval(str);
// document.write(document.getElementById(“divJsText”).InnerHTML);
return false;
}
</script>
</head>
<body>
<form id=”form1″ runat=”server”>
<div>
<div id=”divJsText” ></div>
<asp:Literal ID=”ltrJsText” runat=”server”></asp:Literal><asp:Label ID=”lblJsText” runat=”server”></asp:Label>
<asp:Button ID=”btnAjax” runat=”server” Text=”Ajax请求返回带有JS脚本的文本 JS脚本执行” OnClientClick=”return TestAjaxJs();”/>
</div>
</form>
</body>
</html>
ContainJsText.aspx.cs 代码页面
两种情况:
(1)多个JS语句
namespace AjaxJsTestWeb
{
public partial class ContainJsText : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
StringBuilder jsText = new StringBuilder();
jsText.AppendLine(“<script language=’javascript’>function doit(){alert(‘哈哈,我执行了啊!’);alert(‘哈哈,我再次执行了啊!’);} doit();</script>”);
Response.Write(jsText.ToString().Trim());
Response.End();
}
}
}
(2) 就一个js语句
namespace AjaxJsTestWeb
{
public partial class ContainJsText : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
StringBuilder jsText = new StringBuilder();
jsText.AppendLine(“<script language=’javascript’>alert(‘哈哈,我执行了啊!’)</script>”);
Response.Write(jsText.ToString().Trim());
Response.End();
}
}
}
转自 http://www.taotechinfo.com/collect/2010724/n807115732.html
近期评论