======================================================
注:本文源代码点此下载
======================================================

轉自:http://www.programfan.com

文檔中心:http://www.programfan.com/article/article.asp?classid=3

文件上传是web开发中经常要用到的功能,但asp本身和内置的组件都不支持文件上传功能。网上流

传的一些第三方组件虽然能够解决这个问题,但大多是要收费的,更别说open source了。本文将详细

剖析web文件上传的原理,以及一步步指导读者如何用delphi6开发一个asp上传组件。

源码和demo我已经发布在个人主页上

http://www.wushuang.net

1 html文件分析

首先我们来看一个html文件源码,文件名是test.htm,功能是提供用户上传的界面:

这个文件里包含了一个名为mainform的form,以及随手写的一些input域。注意这个form和一

般的form有两个不同的地方:一是它有一个type=file的域,没有value。用浏览器打开这个文件时,

这个域会表现为一个右侧有“浏览”字样的文件输入框,用户可以通过它来选择本地硬盘上的文件。二是

form有一个特殊的属性:enctype="multipart/form-data"。这个属性告诉浏览器要上传二进制文

件,并进行相应编码。

这种编码会产生什么样的表单信息呢?让我们来看看test.asp,也就是接受表单的asp文件的源码,

它非常简单:

如读者在注释中了解的,这段代码的功能是将表单的原始信息返回。让我们来看看它的运行效果。将

这两个文件置于web目录下,访问test.htm。在文件输入框中,选择一个文件(我选了一个jpg图片,

不过最大不要太大)。提交,然后可以看到这样一堆乱七八糟的信息:

-----------------------------7d2227629012e content-disposition: form-data;

name="mefile"; filename="c:\documents and settings\aaa\my documents\my

pictures\zzjh.jpg" content-type: image/pjpeg (作者注:以下为乱码)

-----------------------------7d2227629012e content-disposition: form-data;

name="a1" fdsaf -----------------------------7d2227629012e content-disposition:

form-data; name="a2" fdsaf -----------------------------7d2227629012e

content-disposition: form-data; name="a3" fdsaf

-----------------------------7d2227629012e content-disposition: form-data;

name="a4" fsdfsdsaf -----------------------------7d2227629012e

content-disposition: form-data; name="a5" 这个是这个

-----------------------------7d2227629012e content-disposition: form-data;

name="a6" fdsaf -----------------------------7d2227629012e content-disposition:

form-data; name="ok" ok -----------------------------7d2227629012e--

这就是用"multipart/form-data"方式编码的表单原始信息。其中那一段看起来是乱码的部分,就

是jpg图片的编码。

分析一下这段信息的格式:

-----------------------------7d2227629012e 这是各个域之间的分隔符。

content-disposition: form-data; 说明这是表单中的域。

name="mefile"; 域的名称。

filename="c:\documents and settings\aaa\my documents\my pictures\zzjh.jpg" 上

传文件在本地硬盘上的名称。

content-type: image/pjpeg 文件类型。

后面是文件本身的数据。

其它各个域的信息也可以以此类推。

众所周知,在asp中,使用request对象,可以访问用户提交表单的各个域。因为request对象

会对原始的表单信息进行解析,提取出表单中每个域的值。但是,request并不能解析这

"multipart/form-data"格式的表单信息。这就是asp不能直接支持文件上传的原因所在。读者可以

试试,在test.asp中,用request("mefile")这样的格式,是不能读取到正确的信息的。

问题的症结已经找到,解决的思路也很简单:用delphi开发一个com组件,接受这种原始表单信息,

将各个域一一提取出来,返回给asp文件。也就是完成request对象没有完成的功能。

2 用delphi开发组件

delphi6对开发asp组件提供了极好的支持,大大简化了我们的开发过程。

启动delphi 6,选择file-new-other-activex-activex library,这样就建立了一个

activex库。将此library改名为myobj,存盘。选择file-new-other-activex-active server

object,在coclassname中填入upfile,确定。这时会跳出一个标题为myobj.tlb的对话框,这是

delphi特有的以可视化方式编辑com接口的功能,用delphi开发过com的读者应该比较熟悉。

在myobj下的名为iupfile的interface下,添加5个属性和一个方法。如果不懂得如何操作,

请参见delphi参考书的相关部分。按f12可以看到生成的相应的myobj_tlb.pas文件,其中的

iupfile接口应该是这个样子:

iupfile = interface(idispatch)

['{5c40d0eb-5a22-4a1e-8808-62207ae04b51}']

procedure onstartpage(const ascriptingcontext: iunknown); safecall;

procedure onendpage; safecall;

functionget_form(formname: olevariant): olevariant; safecall;

functionget_filename: olevariant; safecall;

functionget_filesize: integer; safecall;

procedure filesaveas(filename: olevariant); safecall;

functionget_filedata: olevariant; safecall;

functionget_filetype: olevariant; safecall;

property form[formname: olevariant]: olevariant read get_form;

property filename: olevariant read get_filename;

property filesize: integer read get_filesize;

property filedata: olevariant read get_filedata;

property filetype: olevariant read get_filetype;

end;

其中的onstartpage方法和onendpage方法是delphi默认生成的,其它的是手动加入的。

切换到unit1.pas(也是delphi自动生成的),改名为upfile.pas存盘。可以看到存在一个

tupfile类的声明,它是继承自taspobject类和iupfile接口的。delphi 6已经自动生成了相应

的代码。接下来的任务就是实现这个接口。

除了完成iupfile接口中的属性和方法之后,还需要补充一些东西,以便完成我们的任务。最终的

tupfile类的声明如下:

tupfile = class(taspobject, iupfile)

public

protected

procedure onendpage; safecall;//页面开始

procedure onstartpage(const ascriptingcontext: iunknown); safecall;//页面

结束

procedure filesaveas(filename: olevariant); safecall;//保存文件

function get_form(formname: olevariant): olevariant; safecall;//

function get_filename: olevariant; safecall;

function get_filesize: integer; safecall;

function get_filedata: olevariant; safecall;

function get_filetype: olevariant; safecall;

private

fcontentdata:string;

ffiledata,ffilename,ffiletype:string;

fforminfo:tstringlist;

function instr(str1,str2:string;startpos:integer):integer;

procedure analyformdata(content:string);

end;

下面我们来一一分析这些成员的具体实现。

procedure tupfile.onstartpage(const ascriptingcontext: iunknown);

var

aolevariant : olevariant;

tmpvar : olevariant;

contentlength : integer;

i,delicount,pos1,pos2,lastpos : integer;

fdelimeter : string;

begin

inherited onstartpage(ascriptingcontext);

fforminfo := tstringlist.create;

contentlength := request.totalbytes;

aolevariant := contentlength;

tmpvar := request.binaryread(aolevariant);

for i := 1 to contentlength -1 do

begin

fcontentdata := fcontentdata + chr(byte(tmpvar[i]));

end;

pos1 := pos(#13#10,fcontentdata);

fdelimeter := copy(fcontentdata,1,pos1+1);

delicount := length(fdelimeter);

lastpos := 1;

pos1:=0;

while pos2>=pos1 do

begin

pos1 := instr(fdelimeter,fcontentdata,lastpos);

if pos1 = 0 then break;

pos1 := pos1 + delicount;

pos2 := instr(fdelimeter,fcontentdata,pos1)-1;

analyformdata(copy(fcontentdata,pos1,pos2-pos1-1));

lastpos := pos2;

end;

end;

前面说过,onstartpage方法是delphi自动生成的,在装载页面时发生。在这个方法中,我们完

成一些初始化的任务:读取表单的原始数据,解析表单中的域,并存入相应的属性中,以备调用。

由于delphi已经对asp中的对象进行了很好的封装,所以即使在delphi环境下,也可以方便地调

用它们,就象在asp中一样,例如request.totalbytes。首先将原始表单数据读入到一个

oleviarians类型的tmpvar中,然后通过一个循环,将它转换为delphi中的string格式,并存放

在fcontentdata中。

接下来,通过查找换行符,解析出分隔符的内容和长度。然后在一个循环中,用analyformdata成

员函数一一解析出每个域。初始化工作就这样完成了。

再看analyformdata函数的实现:

procedure tupfile.analyformdata(content: string);

var

pos1,pos2:integer;

formname,formvalue:string;

isfile:boolean;

begin

isfile := false;

pos1 := instr('name="',content,1)+6;

pos2 := instr('"',content,pos1);

formname := copy(content,pos1,pos2-pos1);

//检查是否文件

pos1 := instr('filename="',content,pos2+1);

if pos10 then

begin

pos2 := pos2 + 14;

ffiletype := copy(content,pos2,pos1-4-pos2);

end;

end

else

begin

fforminfo.add(formname+'='+formvalue);

end;

end;

如注释中所表达的,analyformdata提取原始数据中的域。如果是域是文件类型,则将文件类型和

文件数据分别放入ffiletype和ffiledata中。如果是其它类型,则将名称和值放入一个tstringlist

类型的fforminfo中。fforminfo中维护着除文件类型外的所有域的信息,以“名称=值”的格式存放。

function tupfile.get_form(formname: olevariant): olevariant;

begin

result := fforminfo.values[formname];

end;

这个函数返回域的值。只需要简单地调用fforminfo的values方法,就可以得到相应的值。这是

在tstringlist类内部实现的。

function tupfile.get_filename: olevariant;

begin

result := extractfilename(ffilename);

end;

function tupfile.get_filesize: integer;

begin

result := length(ffiledata);

end;

function tupfile.get_filedata: olevariant;

var

i:integer;

begin

result := vararraycreate( [0,length(ffiledata)], varbyte );

for i := 0 to length(ffiledata)-1 do

begin

result[i] := byte(ffiledata[i+1]);

end;

end;

这三个函数分别返回文件的名称、大小、数据。要注意的是,在返回文件数据时,必须进行相应的转

换,将delphi中的string类型转换为olevariant类型。

procedure tupfile.filesaveas(filename: olevariant);

var

fsout:tfilestream;

i:integer;

afile:file of byte;

begin

fsout := tfilestream.create(filename,fmcreate);

for i := 1 to length(ffiledata) do

begin

fsout.write(byte(ffiledata[i]),1)

end;

fsout.free;

end;

这个方法将文件保存到服务器上的磁盘。

编译myobj这个project,得到一个myobj.dll文件。开发工作就此完成。

3 使用asp上传组件

在命令行下,输入“regsvr32 myobj.dll”。弹出一个对话框,告诉你组件已经注册。如果找不到

regsvr32.exe这个文件,它在windows\system32或winnt\system32目录下。

将本文开头提到的test.asp文件修改为如下内容:

再次访问test.htm,提交表单。现在你可以看到相关的返回信息,并且在服务器上test.asp所处

的目录下找到上传的文件。

这个组件只能上传单个文件,但根据同样的原理,一次上传多个文件的功能也是不难实现的。有兴趣

的读者可以自行尝试。

申明

非源创博文中的内容均收集自网上,若有侵权之处,请及时联络,我会在第一时间内删除.再次说声抱歉!!!

博文欢迎转载,但请给出原文连接。

绿色通道:好文要顶关注我收藏该文与我联系

======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/

標題:用Delphi 6開發ASP上傳組件詳解相关推荐

  1. Delphi APP 開發入門(五)GPS 定位功能

    Delphi APP 開發入門(五)GPS 定位功能 分享: Share on facebookShare on twitterShare on google_plusone_share 閲讀次數:3 ...

  2. 【转】ASP.NET验证控件详解(非空验证,比较验证,范围验证,正则表达式,自定义验证)...

    [转]ASP.NET验证控件详解(非空验证,比较验证,范围验证,正则表达式,自定义验证) ASP.NET验证控件详解 现在ASP.NET,你不但可以轻松的实现对用户输入的验证,而且,还可以选择验证在服 ...

  3. ASP.NET验证控件祥解

    ASP.NET是微软推出的下一代WEB开发工具,其强大的功能立即吸引了一大批WEB开发者投入它的靡下.现在,我们来看看ASP.NET的验证控件,感受ASP.NET的强大功能同时方便我们现在的WEB开发 ...

  4. ASP.NET验证控件详解

    ASP.NET六种验证控件,分别如下: RequiredFieldValidator(必须字段验证) 用于检查是否有输入值 CompareValidator(比较验证) 按设定比较两个输入 Range ...

  5. ASP.NET验证控件祥解 (选择自 rko 的 Blog )

    ASP.NET是微软推出的下一代WEB开发工具,其强大的功能立即吸引了一大批WEB开发者投入它的靡下.现在,我们来看看ASP.NET的验证控件,感受ASP.NET的强大功能同时方便我们现在的WEB开发 ...

  6. 我的中間層開發,我的 DataSnap

    歷史篇 DataSnap 和 MIDAS 應用程式和資料庫的關係演變 為什麼要用 DataSnap?--兩層的優缺點 為什麼要用 DataSnap?--DataSnap 解決兩層問題的方法 緣起篇 一 ...

  7. php js asp.net,WebMatrix 3: 方便好用的 ASP.NET、PHP、以及 node.js 網站開發工具

    WebMatrix 3: 方便好用的 ASP.NET.PHP.以及 node.js 網站開發工具 05/02/2013 5 分钟可看完 本文内容 WebMatrix 是由 Microsoft 所開發的 ...

  8. 開博客了, 因為搞Delphi 開發的關於Delphi學習

    開博客了, 因為搞Delphi 開發的關於Delphi學習,之前都是用本地TXT文件保存,發現在本地電腦保存非常不方面,而且只能在一台電腦上保存,不容易查看和修改內容.便於以後的記錄只用,以及經驗交流 ...

  9. delphi 2009 IdSMTP 發郵件中文亂碼問題

    在delphi 2009的發郵件中文會出現亂碼 問題出現的原因估計是由unicode引起的 決解方未法 郵件的正文部分: IdMessage1.ContentTransferEncoding := ' ...

最新文章

  1. As3.0 一些好书连接
  2. Java连接mysql数据库的方式,java连接mysql数据库的方式(4句语句)
  3. Transformer性能优化:运算和显存
  4. css的fill属性,css column-fill属性怎么用
  5. Java Scheduler ScheduledExecutorService ScheduledThreadPoolExecutor示例
  6. PCIE万兆网卡-华硕XG-C100C
  7. python开发技术文档范文_常用python编程模板汇总
  8. python 图像模糊处理实现
  9. ArcGis如何插入图片_如何在CAD图纸中以OLE形式插入图片?
  10. java速成 转载lvsi
  11. 计算机应用基础 项目4-5 分析商品销售业绩 ppt课件,计算机应用基础课件项目四汇总.ppt...
  12. 【SELinux】vendor_file_contexts没有被编译到vendor/etc/selinux/路径下
  13. 使用Java+MapReduce实现热词发现
  14. 雷神加速器无限更新失败️️️
  15. 自车坐标系下的物体相对和绝对位置和速度计算
  16. 《Python数据分析与挖掘实战》示例源码免费下载
  17. 大学计算机实验教程实验6,《大学计算机基础实验教程》参考答案.(6页)-原创力文档...
  18. iOS-脚本打包出现的问题最后居然这么解决了
  19. Android系统自定义关机充电图标
  20. 服务器c盘清理文件,云服务器c盘满了怎么清理

热门文章

  1. 免费领!“梦耀星空·启梦天舟”数字藏品明日上线!
  2. [附源码]JSP+ssm计算机毕业设计温岭市海鲜的捕捞与鉴赏系统3wp88【源码、数据库、LW、部署】
  3. 基于滴滴云搭建微信小程序
  4. XTUOJ ABK(求出A和B的第K大公约数)
  5. 元宇宙仍处于黎明前的暗夜,底层技术基础决定产业未来走向
  6. python合并excel要求_通过Python合并Excel文件,进行,excel
  7. [附源码]Java计算机毕业设计SSM二手书交易软件设计与实现
  8. 正点原子-IMX6ULL学习
  9. 魔域手游3.17服务器维护时间,魔域手游boss刷新时间汇总 boss在哪里刷新
  10. 中国元宵节的习俗至少有12种,你知道多少?