C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[14067] http파일 업로드
김영환 [semon] 1605 읽음    2002-01-01 19:16
active server object 에서요

delphi는

FScriptingContext := AScriptingContext as IScriptingContext

ARequest := FScriptingContext.Request;

FContentLength := ARequest.TotalBytes;

FContentData := VarArrayCreate( [0,FContentLength], varByte );

AOleVariant := FContentLength;

FContentData := ARequest.BinaryRead( AOleVariant );

해서요

빌더에서
      OleVariant    AOleVariant;
      int bounds[2]={0,FContentLength};
      FContentData= VarArrayCreate(bounds,1,varByte);


     try
     {
      Request->get_TotalBytes(&FContentLength)
      AOleVariant=Variant(FContentLength);
      Request->BinaryRead(FContentData,AOleVariant);

Request->BinaryRead(FContentData,AOleVariant); 바이너리 값으로 잃어 오는데

애러가 납니다.  고수님들 부탁드립니다.

혹시 고수님들께 도움이 될것 같아서

delphi 원문을 드리겠슴니다.  그런데 중문으로 되어 있네요  ^^

서버쪽에서 받은 문서 형식은 이러 합니다.

-----------------------------7cf1d6c47c#13#10

Content-Disposition: form-data; name="SaveAs"#13#10#13#10

NewFileName#13#10

-----------------------------7cf1d6c47c#13#10

Content-Disposition: form-data; name="FileData"; filename="D:\test.txt"

Content-Type: text/plain#13#10#13#10

这里是一个用于上载的文件的内容(여기가 문서내용 자리입니다.)#13#10

-----------------------------7cf1d6c47c#13#10

Content-Disposition: form-data; name="b1"#13#10#13#10

확인#13#10

-----------------------------7cf1d6c47c--

그중,“-----------------------------7cf1d6c47c”是分界符(분리부호?^^),用于分隔表单(Form 분리 작용)中的各个域;

#13#10(enter부호 의 delphi 포현방식 입니다.)是回车换行符的DELPHI表示。

二、文件上载的实现过程(문서 업로드 실현과정)




(一)开始建立一个ASP组件的工程(asp 프로잭트)

1、建立ActiveX Library工程

在DELPHI中选择菜单File=》New...,在“New Item”对话框的ActiveX选项卡中选择“ActiveX Library”,DELPHI会自动创建一个DLL工程Project1。

2、建立Automation组件

在DELPHI中选择菜单File=》New...,在“New Item”对话框的ActiveX选项卡中选择“Automation Object”;然后在“Automation Object Wizard”对话框中输入Class Name(如“UploadFile”),Instancing选择“Multiple Instance”即可,单击“OK”后DELPHI会自动创建一个TLB(Type Library)文件Project1_TLB.PAS和一个PAS(Unit)文件Unit1.PAS。在Type Library设计窗口中,将Project1改名为MyUpload,则该文件上载组件的OLE注册码为“MyUpload.UploadFile”。

3、引入ASP类型库

为了使用ASP的五个内建对象(Request、Response、Server、Application、Session),需要引入ASP类型库。我们主要利用Request对象读取从客户端传递到服务器端的数据。

在Project菜单中选择“Import Type Library”,在“Import Type Library”对话框的“Type Libraries”列表选择“Microsoft Active Server Pages Object Library(Version 2.0)”(如果没有这个选项,请确定您的计算机上安装了IIS3以上或PWS4以上并且ASP.DLL已正确注册),DELPHI会自动创建一个TLB文件ASPTypeLibrary_TLB.PAS,其中有我们需要的ASP对象类型声明。

4、定义OnStartPage、OnEndPage过程

当在ASP页面上用Server.CreateObject创建一个OLE对象实例时,WEB服务器会调用其方法OnStartPage,将ASP应用环境信息传递给该对象,我们可以在该过程中获取客户端信息;当在ASP页面中释放一个OLE对象实例时,WEB服务器会调用其方法OnEndPage,我们可以在该过程中进行释放内存等结束操作。在我们这个组件中,我们要用到其OnStartPage方法。

OnStartPage方法应该在Unit1.PAS中定义,OnStartPage的函数原型为:

procedure OnStartPage(AScriptingContext: IUnknown);

其中参数AScriptingContext是一个IScriptingContext类型变量,包含五个属性(Request、Response、Server、Application、Session)分别对应ASP的五个内建同名对象。

我们需要在TLB定义窗口(View=》Type Library)中,为IUploadFile增加方法OnStartPage,其Declaration语句为“procedure OnStartPage(AScriptingContext: IUnknown);”。


(二)提取客户端上传的数据(client data 받기)

该工作可以放在OnStartPage过程中进行。

利用AScriptingContext的属性Request(类型为IRequest)中的属性TotalBytes(请求信息内容长度)和方法BinaryRead可将客户端上传的请求信息数据读取到一个Byte类型的数组中,然后按RFC1867标准定义的数据格式来分析和提取数据。

1、首先定义TUploadFile的几个私有变量 

在单元文件UP01.PAS(由Unit1.PAS另存)中加入对ASPTypeLibrary_TLB.PAS的引用(Uses),

然后加入

private

FContentLength : LongInt;//请求信息内容长度

FContentData : Variant;//内容数据,以数组形式存储请求信息内容

FFileName, //要上载的文件名称

FDelimeter : string; //表单域分界符

FScriptingContext : IScriptingContext;//ASP处理上下文环境内容

FFileDataStart, //文件数据开始位置

FFileDataEnd : LongInt; //文件数据结束位置


2、提取客户端上传的请求信息数据

//在OnStartPage事件中,获取ASP上下文信息、请求信息内容、表单域的分界符、文件数据

procedure TUploadFile.OnStartPage(AScriptingContext: IUnknown);

var

ARequest : IRequest; //WWW请求对象

AOleVariant : OleVariant; //记录请求信息内容长度

intDelimterLength : integer;//分界符长度

longIndex,ALongInt,longPos : LongInt;

ContentData : AnsiString;//请求信息内容的字符串表示

strTemp : string;

FindEndOfFileData : boolean;//是否找到文件数据结束位置

begin

//提取客户端上传的请求信息数据

FScriptingContext := AScriptingContext as IScriptingContext;//获取ASP上下文信息

ARequest := FScriptingContext.Request;//获取WWW请求信息

FContentLength := ARequest.TotalBytes;//请求信息内容长度

//创建动态数组,用于以数组形式存储请求信息内容

FContentData := VarArrayCreate( [0,FContentLength], varByte );

//将请求信息内容存储到数组中

AOleVariant := FContentLength;

FContentData := ARequest.BinaryRead( AOleVariant );//读取请求信息内容

//将请求信息内容转化为字符串,便于定位

ContentData := '';

for longIndex := 0 to FContentLength - 1 do

begin

ContentData := ContentData + chr( Byte( FContentData[ longIndex ] ));

if FContentData[ longIndex ] = 0 then break;//0表示内容结束

end;


3、获取分界符、上载文件名称

//获取表单域的分界符

longPos := pos( #13#10,ContentData );//回车换行符所在位置

FDelimeter := Copy( ContentData,1,longPos-1);//该位置之前的内容为分隔符


//获取带源路径的文件名称,在请求信息内容中,文件名称以

//filename="path/filename"的形式存储

strTemp := 'filename="';//文件名称在“filename="”之后

longPos := pos( strTemp, ContentData );//获取“filename="”位置

if longPos <= 0 then

begin

FFileName := '';

FFileDataStart := -1;

FFileDataEnd := -2;

exit;

end;

//获取下个双引号“"”之前的内容,即带源路径的文件名称

longPos := longPos + length( strTemp );

strTemp := '';

for longIndex := longPos to FContentLength - 1 do

if ContentData[ longIndex ] <> '"' then

strTemp := strTemp + ContentData[ longIndex ]

else break;

FFileName := strTemp;


4、获取文件数据的在请求信息内容中的开始、结束位置

//文件数据开始位置在文件名称后的第一个#13#10#13#10之后

delete( ContentData, 1, longIndex );

strTemp := #13#10#13#10;

FFileDataStart := longIndex + pos(strTemp, ContentData) + length(strTemp) - 1;


//文件数据结束位置在下一个#13#10和分界符之前

//由于文件数据可能包含非法字符,不能再用字符串定位函数POS

//查找下一个分界符的位置

FFileDataEnd := FFileDataStart;

intDelimterLength := length( FDelimeter );

FindEndOfFileData := false;

while FFileDataEnd <= FContentLength - intDelimterLength do

begin

FindEndOfFileData := true;

for ALongInt := 0 to intDelimterLength - 1 do

if Byte( FDelimeter[ ALongInt + 1 ] ) <>

FContentData[ FFileDataEnd + ALongInt ] then

begin

FindEndOfFileData := false;

break;

end;

if FindEndOfFileData then break;

FFileDataEnd := FFileDataEnd + 1;

end;

if not FindEndOfFileData then FFileDataEnd := FFileDataStart - 1//未找到分界符

else FFileDataEnd := FFileDataEnd - 3;//分界符,向前跳过#13#10

end;


(三)向ASP程序传递信息

在进行了(二)的操作之后,我们的上载组件可以根据ASP程序的要求向其传递数据了。目前可以提供的数据有:客户端源文件名称(FFileName,含路径)、文件大小(FFileDataEnd-FFileDataStart+1)。

首先应该在TLB设计窗口中声明如下两个方法GetFileName和GetFileSize。

1、返回客户端源文件名称(含路径)

//返回客户端源文件名称(含路径)

function TUploadFile.GetFileName: OleVariant;

begin

result := FFileName;//客户端源文件名称(含路径)

end;

2、返回文件大小

//返回文件大小(Bytes)

function TUploadFile.GetFileSize: OleVariant;

begin

result := FFileDataEnd - FFileDataStart + 1;

end;


(四)保存文件

在进行了(二)的操作之后,我们的上载组件可以根据ASP程序的要求保存文件了。首先应该在

TLB设计窗口中声明如下两个方法SaveFileAs和SaveFile。

1、按指定文件名称保存文件

//按指定的文件名称保存文件,参数FileName为指定的文件名称,返回值True表示文件保存成功

function TUploadFile.SaveFileAs(FileName: OleVariant): OleVariant;

var

longIndex : LongInt;

AFile : file of byte;//以二进制的形式保存文件

byteData : Byte;

begin

result := true;

try

assign( AFile, FileName );

rewrite( AFile );

for longIndex := FFileDataStart to FFileDataEnd do

begin

byteData := Byte( FContentData[ longIndex ] );

Write( AFile, byteData );

end;

CloseFile( AFile );

except

result := false;

end;

end;

2、按缺省文件名称保存文件

//按缺省文件名称保存文件,将文件以同名文件保存在调用页面所在目录

function TUploadFile.SaveFile: OleVariant;

var

CurrentFilePath : string;

begin

//获取调用页面所在目录

CurrentFilePath := FScriptingContext.Request.ServerVariables['PATH_TRANSLATED'];

CurrentFilePath := ExtractFilePath( CurrentFilePath );

//保存文件

result := SaveFileAs( CurrentFilePath + ExtractFileName( FFileName ));

end;


三、上载组件应用举例

在我们的例子中,DelphiUp.HTM是文件上载界面,DelphiUp.ASP用来执行文件上载操作。

DelphiUp.ASP的代码如下:

<!--DelphiUp.ASP:文件上载处理页面-->

文件上载 <% dim Upload, FileName set Upload = Server.CreateObject("MyUpload.UploadFile") FileName = Upload.GetFileName Response.Write "
正在保存文件《"&FileName&"》......" if Upload.SaveFile then Response.Write "
文件《"&FileName&"》上载成功。" Response.Write "
文件大小为"&Upload.GetFileSize&"字节。" else Response.Write "
文件《"&FileName&"》上载失败。" end if set Upload=nothing %>


四、几点说明

1、由DELPHI自动生成的源代码编译的DLL文件大小有215K,可以在

ASPTypeLibrary_TLB.PAS的Interface段中将Uses中的单元除ActiveX外全部删除,在

MyUpload_TLB.PAS中删除Uses中所有单元,则生成的DLL文件大小可减少到61K。

2、以上方法同样适用于CGI程序,不过要用TWebRequest对象。


以上程序在PWIN98+Delphi3.0+PWS4.0下调试通过。







+ -

관련 글 리스트
14067 http파일 업로드 김영환 1605 2002/01/01
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.