请问如何完成通过HTML页而上载文件?(200分)

  • 主题发起人 主题发起人 Walone
  • 开始时间 开始时间
W

Walone

Unregistered / Unconfirmed
GUEST, unregistred user!
见过一个工具,是 aspsoft提供的,但好象只对English version NT有效
对International version NT 无效。
能否给讲一讲如何去做?
 
如何实现ASP的文件上载和EMAIL的发送?
http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=200987
 
地址:http://www.servlets.com/jsp/examples/ch04/index.html#ex04_17
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.oreilly.servlet.MultipartRequest;
public class UploadTest extends HttpServlet {
public voiddo
Post(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
try {
// Blindly take it on faith this is a multipart/form-data request
// Construct a MultipartRequest to help read the information.
// Pass in the request, a directory to saves files to, and the
// maximum POST size we should attempt to handle.
// Here we (rudely) write to the server root and impose 5 Meg limit.
MultipartRequest multi =
new MultipartRequest(req, ".", 5 * 1024 * 1024);
out.println("<HTML>");
out.println("<HEAD><TITLE>UploadTest</TITLE></HEAD>");
out.println("<BODY>");
out.println("<H1>UploadTest</H1>");
// Print the parameters we received
out.println("<H3>Params:</H3>");
out.println("<PRE>");
Enumeration params = multi.getParameterNames();
while (params.hasMoreElements()) {
String name = (String)params.nextElement();
String value = multi.getParameter(name);
out.println(name + " = " + value);
}
out.println("</PRE>");
// Show which files we received
out.println("<H3>Files:</H3>");
out.println("<PRE>");
Enumeration files = multi.getFileNames();
while (files.hasMoreElements()) {
String name = (String)files.nextElement();
String filename = multi.getFilesystemName(name);
String type = multi.getContentType(name);
File f = multi.getFile(name);
out.println("name: " + name);
out.println("filename: " + filename);
out.println("type: " + type);
if (f != null) {
out.println("length: " + f.length());
out.println();
}
out.println("</PRE>");
}
}
catch (Exception e) {
out.println("<PRE>");
e.printStackTrace(out);
out.println("</PRE>");
}
out.println("</BODY></HTML>");
}
}
 
我对JAVA不懂,但又急着用这个功能,怎么在服务器上用起来呀?请明示
 
Dear Chen:
It is Java1.2? Ido
not find there is a servlet.MultipartRequest just three months ago.
Would you pleasedo
me a favour broadcast the Sundo
cument part about this Class?
 
好歹算是做完了,用了xWolf提供的信息
但本人对VB一窍不通,所以也没有改。
trycy.chen提供的代码好象要装了java web server才能编译吧?只是IIS好象行不通的。

 
确实是要装java web server.
可以装jrun or tomcat for iis .
 
诸位老兄:
我下载 com.oreilly.servlet.MultipartRequest ,UploadTest.java 和 Upload.htm 原码
编译后执行: 有如此错误:

Error: 500
Internal Servlet Error:
java.lang.LinkageError: trying to refine class UploadTest (bad class loader?)
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java, Compiled Code)
at java.lang.ClassLoader.defineClass(ClassLoader.java:392)
at com.sun.web.core.ServletLoader.loadClass(ServletLoader.java:117)
at com.sun.web.core.ServletLoader.loadServlet(ServletLoader.java:31)
at com.sun.web.core.ServletWrapper.loadServlet(ServletWrapper.java:91)
at com.sun.web.core.ServletWrapper.handleRequest(ServletWrapper.java:119)
at com.sun.web.core.InvokerServlet.service(InvokerServlet.java:168)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:840)
at com.sun.web.core.ServletWrapper.handleRequest(ServletWrapper.java:155)
at com.sun.web.core.Context.handleRequest(Context.java:414)
at com.sun.web.server.ConnectionHandler.run(ConnectionHandler.java:139)

com.oreilly.servlet.MultipartRequest.java 实在难懂!!
我的环境:jdk1.2.2 , Jsdk2.0 , Jswdk-1.0.1
各位大虾:能否帮帮小弟,在下感激不尽。
 
使用ASP(转载):
用DELPHI为ASP开发文件上载组件 深圳王发军

ASP(Active Server Page)是微软公司的产品,由于它编程很容易上手,能快速开发功能强大的动态网站,现在很多网站(特别是Intranet/Extranet内部网)采用了NT+IIS+ASP的模式,使得ASP成为目前较为流行的网站开发脚本语言。在WEB服务中,文件上载服务是一个很常见的功能,而WIN9X下的PWS没有提供相关组件;NT下的IIS提供了一个Post Acceptor组件,但由于它要检查用户的WWW访问权限而变得不太好用;也可以从Internet上下载有关组件,但这些大多都是商业组件,用于下载的是试用版,在使用时间或功能上都有限制。由于ASP可以调用标准的OLE/COM组件,我们可以用VB/VC/DELPHI等高级编程工具根据我们自己的要求来定制自己的ASP文件上载组件,满足自己的应用系统要求。
  下面将讨论用DELPHI为ASP开发文件上载组件的原理和具体实现过程。

一、文件上载的实现原理
  基于Web方式数据上传,要遵从RFC1867标准,上载的文件数据也不例外。如用下面HTML页面文件(delphiup.htm)选择上载文件:
<!-- DelphiUp.htm:文件上载界面 -->
<html><head><title>文件上载</title></head><body>
用DELPHI编写的文件上载组件实现文件上载
<form NAME="UploadForm" ACTION="delphiup.asp" METHOD="POST" ENCTYPE="multipart/form-data">
<p>文件另存为:<input TYPE=text NAME="SaveAs">
<p>请要选择上载的文件:<input TYPE=file NAME="FileData">
<input type="submit" name="b1" value="确认上载"> </p>
</form>
</body></html>
  当客户端选择了一个文件(如Test.TXT,其内容为“这里是一个用于上载的文件的内容。”)并按
“确认上载”按钮提交数据后,服务器端程序收到的数据将具有如下形式:
-----------------------------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是回车换行符的DELPHI表示。我们可以这样认为,每个表单域的信息描述,都是以分界符加一对回车换行符#13#10开始;表单域名以“name="”开始,以“"”为结束;表单域值以两对回车换行符#13#10#13#10开始,以一对回车换行符#13#10#加分界符结束;文件名称以“filename="”开始,以“"”为结束。有了这些标志,我们就可以获取表单域的名称和值以及要上载的文件的名称,从而实现文件数据的读取和存储了。

二、文件上载的实现过程
  在理解上面提到的数据格式后,自己动手编写一个文件上载组件对我们来说已经不是困难了。

  (一)开始建立一个ASP组件的工程
     如果您对用DELPHI开发OLE Automation Server的步骤不太熟悉的话,请参见《电子与电脑》1999年第06期的一篇文章《用DELPHI开发用于ASP的OLE Automation Server 》。
这里只简要介绍一下操作步骤。
  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);”。

  (二)提取客户端上传的数据
  该工作可以放在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 - 1do

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 - 1do

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 - intDelimterLengthdo

begin

FindEndOfFileData := true;
for ALongInt := 0 to intDelimterLength - 1do

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 FFileDataEnddo

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:文件上载处理页面-->
<html><head><title>文件上载</title></head><body>
<% dim Upload, FileName
set Upload = Server.CreateObject("MyUpload.UploadFile")
FileName = Upload.GetFileName
Response.Write "<br>正在保存文件《"&amp;FileName&amp;"》......"
if Upload.SaveFile then

Response.Write "<br>文件《"&amp;FileName&amp;"》上载成功。"
Response.Write "<br>文件大小为"&amp;Upload.GetFileSize&amp;"字节。"
else

Response.Write "<br>文件《"&amp;FileName&amp;"》上载失败。"
end if
set Upload=nothing %>
</body></html>

四、几点说明
  1、由DELPHI自动生成的源代码编译的DLL文件大小有215K,可以在
ASPTypeLibrary_TLB.PAS的Interface段中将Uses中的单元除ActiveX外全部删除,在
MyUpload_TLB.PAS中删除Uses中所有单元,则生成的DLL文件大小可减少到61K。
  2、以上方法同样适用于CGI程序,不过要用TWebRequest对象。






  
 
奇怪,明明分过一次脏,怎么还不结账,难道还要一次??
 
我就不信银子分不出去!!!!
 

Similar threads

回复
0
查看
848
不得闲
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部