2008 年 09 月

浏览模式: 标准 | 列表 | 图文

闲着无聊,用WPS生成文档

不好意思,该操作只能在windows服务器上才能执行,是因为,只有windows服务器才支持COM功能,而且,必须安装wps(这点应该不难,因为WPS是免费软件)
免费软件这点太重要了,如果你要生成WORD,你不可能安装一个OFFICE吧,office太贵了。

<?php
$wps = new COM("WPS.Application");
$wps->Visible = false;
$doc = $wps->Documents->Add();
$doc->Range->Text = 'WPS FOR PHP test';
$doc->Paragraphs[1]->Alignment = 1;
$doc->Shapes->AddPicture("http://img.kingsoft.com/publish/kingsoft/images/gb/sy/logo.gif", 100, 50, 148, 60);
$doc->SaveAs('c:\\temp\\test1.wps');
$doc->Close();
$wps->Quit();
unset( $doc , $wps );
?>

代码很简单,只是添加了一个文字和一个图片而己。但是,证明了是可以使用这个功能。
大家别忘了,WPS的附加功能可是很多的,比如把文件转为PDF等格式。也就是说, 如果是在windows服务器上,我们要生成PDF,可以不使用那些什么fpdf类库,而是使用WPS先生成一个WORD格式的文档,然后直接exportPdf就可以了。要知道OFFICE默认并不支持这种功能。黑黑

这也是一种思路嘛,思路决定出路,转换一种思路,可能就是海阔天空。

这里是WPS的开发者网站:http://wps.kingsoft.com/apply/engineer.shtml,从这里可以下载API:http://wps.kingsoft.com/download/WPSAPI.zip

为windows的WEB服务器添加高性能的FTP组件

为windows的WEB服务器添加高性能的FTP组件

在windows服务器里面,如果我们要用FTP函数,速度应该是很慢的,而且效率不高,如果有大量文件需要上传,用自带的FTP函数,恐怕是要死人的吧。
windows服务器,windows哦,可以装N多软件的windows哦。虽然不建议在服务器上装上很多软件,但是也可以装一些FTP软件的嘛。这里以cuteftp举例。
cuteftp安装完毕后,会在软件目录里有一个Scripts目录,现在的版本不象很久以前的了,如今的版里只有一个Sample.vbs,记得几年前的cuteftp里面会有各种各样的vbs文件的。
闲话不多说,打开vbs文件,内容为:

'This default template script is in VBScript. You can write scripts in your language of choice and save them with the proper extension, or use your an editor specific to that language.
'See the TESDK help file for more details on how the scripting feature works and for information on each supported method and property.
'You must have Windows Scripting Host installed for the COM enabled engine to work. Run the Transfer Engine once to register it (as a COM object) on the target system.
'If you're having problems with running scripts while not logged in, or when trying to run them using MS scheduler, refer to our online knowledgebase for help (http://www.globalscape.com/support)
'Look into c:\temp folder to observe local activity (for testing purposes) or right click on the Transfer Engine icon in the systray and select "show current transfers"
'This sample script performs an anonymous login to ftp://ftp.globalscape.net
'First declare a variable called Mysite. This will hold the reference to the TE COM object.
Dim MySite
'Create a connection object and assign it to the variable
Set MySite = CreateObject("CuteFTPPro.TEConnection")
' Now set each property for the site connection
' You can omit this section to use the default values, but you should at least specify the Host
'The default Protocol is FTP, however SFTP (SSH2), FTPS (SSL), HTTP, and HTTPS can also be used)
MySite.Protocol = "FTP"
MySite.Host = "ftp.globalscape.com"
'following lines are optional since the default is anonymous if no login and password are defined
MySite.Login = "anonymous"
MySite.Password = "user@user.com"
'if necessary, use the UseProxy method and ProxyInfo or SocksInfo properties to connect through a proxy server
MySite.UseProxy = "BOTH"
'now connect to the site (also called called implicitly when most remote methods are called)
MySite.Connect
'perform some logic to verify that the connection was made successfully
If (Not Cbool(MySite.IsConnected)) Then
MsgBox "Could not connect to: " & MySite.Host & "!"
Quit(1)
End If
'The script will now check to see if the local folder c:\temp exists and will create it if necessary
If (Not (MySite.LocalExists("c:\temp"))) Then
MySite.CreateLocalFolder "c:\temp"
End If
'Change TE's local working folder to to c:\temp
MySite.LocalFolder = "c:\temp"
'Check for existence of remote folder "/pub/cuteftp"
b = MySite.RemoteExists("/pub/cuteftp/")
If (Not CBool(b)) Then
'Verify existence of remote folder
MsgBox "Remote folder not found!. Please make sure that the Pub folder exists on the remote site"
Quit(1)
End If
'Now download the index file to the local destination folder
MySite.Download "/pub/cuteftp/index.txt"
'Complete. Show the status of this transfer.
MsgBox "Task done, final status is '" + MySite.Status + "'"
MySite.Disconnect
MySite.Close
'End of sample script. You can save you script and then run it by either selecting it from the Tools > Run Script menu or by double clicking on the script file in Windows

看到这样的文件,你应该知道如何调用一些FTP软件自带的方法了吧?

由于windows版本下的PHP直接就支持COM,所以现在我们可以直接用PHP模拟一遍:

<?php

$ftp = new COM("CuteFTPPro.TEConnection");

$ftp->Protocol = "FTP";
$ftp->Host = "ftp.globalscape.com";

$ftp->Login = "anonymous";
$ftp->Password = "user@user.com";

$ftp->UseProxy = "BOTH";
$ftp->Connect();

if ( !$ftp->IsConnected ){
die("Could not connect to : {$ftp->Host}");
}

if ( !$ftp->LocalExists('c:\\temp') ){
$ftp->CreateLocalFolder('c:\\temp');
}

$ftp->LocalFolder = 'c:\\temp';

$remote = $ftp->RemoteExists('/pub/cuteftp/');
if ( !$remote ){
die('Remote folder not found!. Please make sure that the Pub folder exists on the remote site');
}

$ftp->Download('/pub/cuteftp/index.txt');
echo( 'Over,ftp Status:' . $ftp->Status );
$ftp->Disconnect();
$ftp->Close();


?>

执行一下,OK,显示:Over,ftp Status:FINISHED,同时c盘根目录下有一个temp目录,里面下载了那个:index.txt文件。测试完毕。。(PS:对于这样的转换实在没有技术含量啊。呵呵,直接把“.”换成“->”就完事了。)
更多的函数,请参考cuteftp帮助文件:

5c935efdda14f3d98286d16baf2239f2
精通MYSQL数据库——连载七

精通MYSQL数据库——连载七

今天我们继续学习一下MYSQL的数据类型
浮点型
从MYSQL3.23开始,FLOAT和DOUBLE类型就一直分别对应着IEEE标准所定义的单精度浮点数和双精度浮点数,绝大多数编程语言也都支持这两种数据类型。
当某个字段设置成这两种类型时,会要求按(m,d)这样的格式输入参数,其中m和上文介绍INT时所讲的m效果一样,仅仅在显示/打印结果时有一定的排版作用,而对数据的精确度没有影响。可是d这个参数就不一样了,d代表了小数点后面的数字个数,而且会按照d的大小来进行四舍五入,例如:1234.5678如果存储到FLOAT(8,3)这样的字段里,实际存放的是1234.568,最后一位会四舍五入。
存储FLOAT和DOUBLE时,如果超出了这两种类型的范围,将会被替换成该类型的最大可取值(一般由当前操作系统决定,我不知道MYSQL是怎么样。),可以使用SHOW WARNING来查看警告内容。
MYSQL对浮点数有一定的要求,即一定要符合通用计数法,小数点一定是“.”,而不能是“,”(因为有部分欧洲国家使用逗号作为小数点,我也是第一次听说,黑黑),MYSQL永远会以这种写法向客户返回查询结果,只有在非常大或非常小的数值,会采用科学计数法表示,如1.234E+017。如果想让浮点数表现形式变成其他样式,有两种方式:一是利用SQL查询中的FORMAT函数,二是用客户端程序中的FORMAT函数,例如php中就可以使用sprintf或者number_format等来改变显示效果

类型 含义
FLOAT(m,d) 单精度浮点数,8位精度,占4字节
DOUBLE(m,d) 双精度浮点数,16位精度,占8字节
REAL(m,d) DOUBLE的同义词



说到浮点数,当然要提定点数了
正因为MYSQL在处理浮点数时,最后一位会被自动的四舍五入,而我们实际上并不需要这一位被四舍五入(比如在处理财务数据时),怎么办呢?定点数可以解决这个问题。
定点数(DECIMAL)数字是以字符串的形式来进行存储的,并且不被允许存储指数形式,每位数字占用一个字节,外加两个字节的开销,所以,占用了更多的空间,但可表示的数值范围却比较小。
在进行存储的时候,也有两个参数DECIMAL(p,s)这回,这两个参数都有作用了。p代表了数据的总位数(不含小数点),最大65,s代表了小数点后的数字位数,最大为30。比方说:DECIMAL(6,3)取值范围为-999.999~999.999,这是新的版本的表示方法。不知道我有没有记错,我记得在以前的版本里,DECIMAL(6,3),这个6并不是代表了总位数,而是小数点前的位数(可能是在4.0吧)。
在MYSQL内部,定点数是被保存为二进制格式的,把定点数从小数点开始分割,并为它们各自分配所占用的字节数(最初是以每4个字节进行划分,虽然每个字节可以容纳2位数字,但4个字节却可以容纳9位数字,超过4个字节后,如果有多出的数字就划分一个字节来进行存储,同样如果是9位数字,还是只占4个字节)。根据这个规定,我们可以认为DECIMAL(6,3)其实是和DECIMAL(18,9)占用了同样多的字节数(8个字节)。如此说来DECIMAL(19,9)实际就占用了9个字节。

类型 含义
DECIMAL(p,s) 定点数,以字符串形式保存,最长为65
NUMERIC,DEC 同上(应该没有记错吧)

参考:http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html

让手机迅速变成空号

让手机迅速变成空号

有的时候你不想接别人的来电,但是又不想被别人知道你不想接,怎么办?一般来说有以下几种方法:
1、开机的时候,取电池,会有该用户暂时无法接通的提示
2、黑白名单,这个应该是最有效最安全的
3、输入**21*999999#,拨号,会让号码暂时变成空号,手机上会显示一个电话+一个箭头,恢复的时候按##21#再按拨号就恢复了。

中秋快乐

这首词,梅艳芳也唱过,不过,斯人已远去,我等俗人无法再次回忘,值此中秋佳节,送上此词来缅怀先辈,同时也祝福所有的人都快乐。(顺便给自己放假一下,呵呵)

明月几时有
把酒问青天
不知天上宫
今夕是何年

我欲乘风归去
唯恐琼楼玉宇
高处不胜寒
起舞弄清影
何似在人间

转朱阁低绮户照无眠
不应有恨何事长向别时圆
人有悲欢离合月有阴晴圆缺
此事古难全
但愿人长久千里共婵娟

苏轼(苏轼是谁,我应该不用介绍了吧。。。再介绍就变成语文课了)

身为WEB开发人员,真是痛苦,ietester解决部分痛苦

身为WEB开发人员,真是痛苦,ietester解决部分痛苦

身为一个WEB开发人员,最痛苦的是什么?不是那些程序,而是程序在不同的浏览器里所需要达到的效果。看看现在有多少浏览器吧,咱们先不谈那些在linux下面使用的浏览器。不是说不照顾他们,而是,他们使用的核心也大多差不多,再加上使用量确实少,咱们就先忽略一下。希望不要生气。
IE是市场份额最大的浏览器了吧。自从畅游推出了MYIE并开源之后,国内多窗口浏览器的发展就开始蒸蒸日上了,什么gb,tw,maxthon等等等等。这是FOR IE核心的。
非IE核心的,大多是三种GEKEO,webkit,opera三大阵营,算是使用量特别多的。
因此,作为一个WEB开发人员,就不得不考虑这四大类型的浏览器,而其实,问题最多的还是IE,毕竟其他的三个核心还算是遵守W3C规范,而IE就只能算是特立独行,却偏偏它所占的市场份额最高。
IE,如果就一个IE,那也就算了,可是从IE5.5开始,6、7、8没有一个是完全一样的,所遵从的规范也都不一样,这才是痛苦之源。
推荐一个软件Ietester,整合了4个核心的IE,。5.5、6、7、8beta2,这回,测试的时候可以方便一点,最起码一个程序可以完成以前的效果(仅仅是测试而己)。
其他的我不介绍,这里只有截图。。。
7d8e79d4311db07d51119a4eb56344fe
网址是:http://www.my-debugbar.com/wiki/IETester/HomePage

已知问题:

Known problems and limitations :

  • When resizing, the content may disappear. I am working to correct it on the next version.
  • The Previous/Next buttons are not working properly
  • Focus is not working properly
  • Java applets are not working
  • Flash is not working on IE6 instance.

希望可以给WEB开发者带来方便。

全屏截图:

c12ee2f684f4f376e9218a226e25689b

精通MYSQL数据库——连载六

精通MYSQL数据库——连载六

介绍完表的结构和存放位置后,下面的内容就是介绍MYSQL的数据类型了,毕竟为你想要的数据选定一个合适的类型,对于数据库的存取效率有很大的改进。
MYSQL数据库有以下几种类型:整数型(int,binint,smallint,tinyint等等xxxint型)、浮点型(float,double,real等)、定点数型(decimal,也就是传说中的浮点型的字符串表达形式)、日期与时间型(data,time,datetime,timestamp),字符串型(char,varchar,text,tinytext,mediumtext,longtext等),二进制型(tinyblob,tinyblob,blob等blob型),枚举型(enum,set——set是类似于enum型)。

下面从整数型开始详细介绍这些数型的基本信息:
整数型
默认情况下,INT类型既包括正数,也包括负数,如果给INT列定义UNSIGNED属性,那么它的取值范围就永远是正数。这个永远是正数,非常重要,即,如果你在对数据列操作:update tablename set int_field = (int_field - 1000 ),如果int_field的值小于1000,理论上是变成了负数,但由于你设的属性是UNSIGNED,那么存储的数据仍然是无符号的正数,这可能会给你带来虚假或让人困惑的结果。
TINYINT的取值范围是从-128~+127,如果使用了UNSIGNED属性,那么它的取值范围就变成了0~+255。如果用户试图存入超过字段取值范围的数字,MYSQL所做的工作就非常简单,它会直接替换成最大可取值或最小可取值。
或许有人注意到,我们在使用phpmyadmin的时候,如果选择INT类型,那么后面有一个可选长度。不过,千万不要被这个数值所迷惑,因为它的实际功能并非指定该INT类型的长度,而是最大显示宽度(M:Maximum Display Width),仅仅用于查询数据时可以把查询结果按照你所指定的宽度进行显示,最主要的用途是为了排版需要。虽说是这样,但在一些很少见的特定场合(MYSQL在执行一些需要借助于临时数据表才能完成的复杂查询)里,临时数据表的数值有可能会被截短并导致最终结果不正确。因此,除非你与数据库所有的操作都在命令行下执行,否则,还是建议留空。

INT 类型 该类型的实际含义
Tinyint(m) 8位整数,占用1个字节(-128~+127)
smallint(m) 16位整数,占用2个字节(-32768~+32767)
medimumint(m) 24位整数,占用3个字节(-8388608~+8388607)
int(m),integer(m) 32位整数,占用4个字节(-2147483648~+2147483647)
bigint(m) 64位整数,占用8个字节(-9.22E+18 ~ +9.22E+18)
serial 这其实是bigint auto_increment not null primary key的简写

上面tinyint(m)括号中的m,就是上文所指的最大显示宽度。最后一个serial含义里的auto_increment,代表了该字段是自增字段,即,往有该属性的字段里插数据时,系统会自动把该字段的当前最大值加上1后存进去。 一般而言,该属性往往用于主键字段。在使用该属性时应当注意以下几个问题。
1、该属性必须与NOT NULL、primary Key 或者 Unique属性同时使用。
2、每个数据表只能存有一个auto_increment属性的数据列
3、该属性一般是在进行数据插入时,没有明确指定值或者指定值为NULL时,才起作用。如果指定了值,并且该值还没有出现过,MYSQL将使用该值插入,以生成一条新记录。这时候就有两种情况:a)原有的数据是1~100,后来删除了20~80的内容,即数据库里只存在1~19,81~100的数据,当插入ID为20的数据时,数据库还是会按照规则,把20这条记录插进去,并不会报错,自增值仍然是100,下次正常插入时,还是会默认使用101这个值。b)原有的数据是1~100,我插入ID为1000的数据时,不会报错,但自增值变为1000,下次插入数据从1001起算。(啰嗦了点,但应该记住)
4、如果想知道刚刚插入的数据值是多少,在插入数据后,可以使用select last_insert_id()语句获取。在PHP中,有一个函数是:mysql_insert_id(),该函数不是很建议使用,因为它返回的数据是INT型,如果auto_increment所在的数据列类型是bigint,而且实际值已经超过int类型最大值的话,mysql_insert_id()返回的值,将不正确。
5、如果auto_increment计数器达到了最大值(即该字段所允许的最大值),将不再递增,因此数据插入将无法执行。其实是到了最大值后,MYSQL会永远将该字段的最大值往数据库里插,因此造成MYSQL报:该数据列已存在的错误。
6、如果在可行范围内,或者预计数量会很大的情况下,尽量使用你想要设定的数据类型的再上一层类型,但尽量不要太夸张。比如你预计你的用户数不会超过1000000万,表面上medimum无符号已经够用了,但这时候,仍然建议你使用int型,以防万一。

打字很累,剩下的留到以后慢慢讲。。。

差点忘了。。。还有个BIT和BOOL,在MYSQL中,关键词BOOL是TINYINT的同义词,在5.0.2以及以前的版本中,BIT也是如此。但是从5.0.3开始,BIT不再是TINYINT的同义词,而是一种可以存储多达64位二进制数值的新数据类型。这个在以后会单独介绍,这里一笔带过先。

精通MYSQL数据库——连载五

精通MYSQL数据库——连载五

明天,就是俺结婚2周年的纪念日了,为了感谢大家的支持,所以。今天再开放一篇连载。黑黑

介绍完MYSQL所支持的一些数据表类型,再介绍一下数据表文件的存放等资料。

MYSQL对于数据表的存放一般而言都是很有规律的,在*nix系统下面,通常在/var/lib/mysql子目录,而在windows平台下一般都在mysql安装目录下的子目录/data/里。

(写了一半,发现都需要用到数据存放目录,现在假设数据存放目录为/data/)

一般而言,每一个数据表都有一个和表名对应的frm文件,而这些数据表都是存储在以它本身所在数据库为名的目录里。例如:User数据库下的members表,一般都存储在数据库目录下的/User/下,名字为members.frm(全路径为:/data/User/members.frm)。frm文件是整个数据库的结构定义和设置。

如果是myisam数据表,那么还会创建两个以数据表命名的文件,*.MYD,*.MYI,其中MYD文件用来存放MYISAM数据表的数据,而MYI文件用来存放索引(该表的所有索引)。

如果是innoDB数据表的话,就需要根据MYSQL配置文件中的innodb_file_per_table的选项设置情况而定。它既可以各自存为一个文件,也可以统一存放在所谓的表空间(tablespace)里。表空间的存放位置和名字由配置决定。如果没有做任何设置的话,默认是innodb数据表的数据和索引存放在/data/dbname/tablename.idb文件里,而把表空间和撤销日志(undo log)存放在/data/ibdata1,/data/ibdata2/...等文件里,而把innodb的日志数据存放在/data/ib_logfile0 ,/data/ib_logfile1这样有规则的文件里。

在如今的版本里,如果你定义了触发器,那么它们存放在/data/databasename/tablename.TRG文件里。新版本据说可能会发生变化。

[精][转]Apache多虚拟主机的简单配置

[精][转]Apache多虚拟主机的简单配置

打开google reader,好开心,发现一篇精品文章,不敢独享,放上来。毕竟,独乐乐不如众乐乐嘛。没看这篇文章之前,我一直没有想通,那些空间商是怎么让一个用户注册一下就生成一个空间,而不用重启apache的。这一直是我的心头疑问,直到看到这篇文章的黑体字,所以。。。。转摘一下,哈哈

作者:FinalBSD
日期:2008-09-11
原文地址:http://www.sanotes.net/html/y2008/181.html
需求:
一台apache上要服务很多的虚拟主机,这些虚拟主机的域名具有规律性,比如说是:xxx.example.com

实现:
使用mod_rewrite进行跳转
优点:
* 不需要为每一个虚拟主机配置一段;
* 新增了vhost不需要重启apache,只需要编辑vhosts.map即可;

缺点:
* 无法为特定的vhosts设定具体配置

配置:

RewriteEngine On
RewriteMap lowercase int:tolower

RewriteMap vhost txt:/usr/local/etc/apache22/vhost.map
RewriteCond ${lowercase:%{SERVER_NAME}} ^(.+)$
RewriteCond ${vhost:%1} ^(/.*)$
RewriteRule ^/(.*)$ %1/$1

/usr/local/etc/apache22/vhost.map的内容是:

site1.example.com /usr/local/www/data/1
site2.example.com /usr/local/www/data/2
site3.example.com /usr/local/www/data/3
site4.example.com /usr/local/www/data/4
site5.example.com /usr/local/www/data/5
site6.example.com /usr/local/www/data/6

原理:
1.构建2个映射表,分别是lowercase和vhost;
2.对每个URL进行RewriteCond检查,比如http://Site5.Example.com/index.html
2.1 第一条RewriteCond:

RewriteCond ${lowercase:%{SERVER_NAME}} ^(.+)$

1)这里首先查询lowercase表,lowercase表属于int类型,使用apache内部函数tolower将

key:Site5.Example.com替换为value:site5.example.com.

2)查完之后用查询到的Value进行RewriteCond判断

input='site5.example.com' pattern='^(.+)$' => matched

2.2 第二条RewriteCond:

RewriteCond ${vhost:%1} ^(/.*)$

1)这里首先查询vhost表,vhost表属于txt类型,key:site5.example.com对应value为/usr/local/www/data/5.
2)查完之后用查询到的value进行RewriteCond判断

input='/usr/local/www/data/5' pattern='^(/.*)$' => matched

3.在2条RewriteCond都符合的情况下,执行RewriteRule规则:

RewriteRule ^/(.*)$ %1/$1

将/下面的所有文件重写到%1/$1,这里的
%1:是上一个RewriteCond的value:/usr/local/www/data/5
$1:即(.*)的括号里面的内容,即请求的文件名
最终的执行为:

rewrite '/index.html' -> '/usr/local/www/data/5/index.html'

可以看详细的日志了解整个过程。
requested uri /index.html

192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (3) applying pattern '^/(.*)$' to uri '/index.html'
192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (5) map lookup OK: map=lowercase key=site5.example.com -> val=site5.example.com
192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (4) RewriteCond: input='site5.example.com' pattern='^(.+)$' => matched
192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (6) cache lookup FAILED, forcing new map lookup
192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (5) map lookup OK: map=vhost[txt] key=site5.example.com -> val=/usr/local/www/data/5
192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (4) RewriteCond: input='/usr/local/www/data/5' pattern='^(/.*)$' => matched
192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (2) rewrite '/index.html' -> '/usr/local/www/data/5/index.html'
192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (2) local path result: /usr/local/www/data/5/index.html
192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (1) go-ahead with /usr/local/www/data/5/index.html [OK]

Reference:Apache模块 mod_rewrite

更强大的方法:使用mod_vhost_alias(由Tonny推荐):

UseCanonicalName Off
VirtualDocumentRoot /usr/local/www/data/%0

那么对http://site1.example.com/file.html的请求将会返回文件/usr/local/www/data/site1.example.com/file.html
Reference:Apache模块 mod_vhost_alias

Appendix:比较专业的模块(i_amok推荐)
http://www.oav.net/projects/mod_vhs/