ISAPI上传问题,请大家进来看看。(100分)

  • 主题发起人 主题发起人
  • 开始时间 开始时间
to kyq
请问你用MSN吗?交个朋友吧 pjntt@hotmail.com
 
Sorry for the delay.

"其实无论循环还是一次
性读取数据,在我没有把这些数据处理、存盘前,那么它们都是存放在内存里了。"
其实不是这样,数据还没从客户机传过来,ReadClient时才进行读取。

摘自MSDN:
(mk:@MSITStore:C:/Program%20Files/Microsoft%20Visual%20Studio/MSDN98/98VS/2052/IISRef.chm::/devdoc/good/iishelp/iis/htm/sdk/appref_235g.htm)
The ReadClient function reads information from the body of the
Web client's HTTP request into the buffer supplied by the caller.
Thus, the call can be used to read data from an HTML form that
uses the POST method. If more than lpdwSize bytes are immediately
available to be read, ReadClient will block until some amount of
data has been returned, and will return with less than the requested
amount of data. In order to ensure that all data has been read,
your program should call ReadClient in a loop which continues to run
until the amount of data specified in lpdwSize has been read.
If the socket on which the server is listening to the client is closed,
ReadClient will return TRUE, but with zero bytes read.

从实际来说,"一次读取全部数据"和"使用循环去读取数据,其实是用小缓冲区处理大量数据",
也就是"能用"和"工作良好"的区别。

一次读取全部数据是能用,但消耗服务器资源过多,不太切合实际,但编写容易。
使用循环去读取数据,其实是用小缓冲区处理大量数据,编写困难,但是在实际应用中是
必须的,属于工作良好。

"再,我发觉几朋友提供的代码都是一次读取数据是不超过48K的,
也就是上传数据超过48K的的时候就要循环读取了。这个48K是ISAPI本身规定的吗?"
看看以下:
摘自MSDN:
(mk:@MSITStore:C:/Program%20Files/Microsoft%20Visual%20Studio/MSDN98/98VS/2052/IISRef.chm::/devdoc/good/iishelp/iis/htm/sdk/filtoview_9svb.htm)
If the client is sending POST data with the request,
and all of the data was not read in the first step,
one or more SF_NOTIFY_READ_RAW_DATA notifications will occur here.
Data will be read until either 48K of data is received from the client,
or until all of the data is read, whichever occurs first.
The 48K read size is typical, but it may be varied. For example,
if the MD_UPLOAD_READAHEAD_SIZE in the metabase has been set to a value
other than 48k, IIS will attempt to read that amount of data.
Other factors can impact how much the server reads so filters
should not rely on this exact behavior.
......
If the handler calls ReadClient to continue reading POST data beyond 48K,
one or more additional SF_NOTIFY_READ_RAW_DATA notifications will occur.

其实说这么多,就是避免兼容性问题。
好像大于48KB,在IIS V4.0下就不时出现死锁。
 
我可能要卸掉MSN Messager了。
不太喜欢用,有被微软强制使用的感觉,打开Outlook时竟然强制运行MSN Messager。

还是用QQ吧。
My QQ:21859686
 
to kyq
谢谢您的回答。我已加你为好友。
“好像大于48KB,在IIS V4.0下就不时出现死锁。”
那么按你这么说,ASP的readbinary方法的内部操作其实也是循环读取数据?
只是这方法的的内部操作对我们来说是透明的?
 
呵呵,对不起,打错字了,,是应该是binaryread方法

我看了一下,却怎么也找不到binaryread方法的代码[:(]
 
to kyq
我试了你的代码,很成功上传了文件。但其中又发现了一个问题。当最后一次读取数据不足
48K的时候,程序却在一直等待数据,直到超时,这有什么办法解决吗?
 
枫 said:我在试这个代码的时候,虽然数据传完了,但是程序还是在等待,一直到客户端超时呢

再看看:
procedure TWebModule1.WebModule1WebActionItem1Action(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
fs:TFileStream;

Size:Integer;

Buffer:Array [0..8192-1] of Byte;//奇怪,只有8192才能正常。当使用>8192时,第一次上传速度正常,以后就很慢了。

TotalBytes:Integer;
begin
fs:=TFileStream.Create('C:/Temp/aa/data.txt',fmCreate);
try
fs.Write(
PChar(Request.Content)^,
Length(Request.Content)
);

TotalBytes:=Request.ContentLength-Length(Request.Content);

while TotalBytes>0 do
begin
Size:=Request.ReadClient(Buffer[0],High(Buffer)+1);
if Size<=0 then
break;//It should raise an exception here.

fs.Write(
Buffer[0],
Size
);

TotalBytes:=TotalBytes-Size;
end;


finally
FreeAndNil(fs);
end;

Handled:=true;
end;
 
刚才我试验了你的代码,发现这样的问题,当小于8K的时候,CPU的工作时间消耗就越高,
不过处理也越快,大于8K的时候(我只试到把缓冲区设为20K)就相反,,这是怎么回事?
 
我在MSDN上找到的,,有点帮助

Extension Control Block member lpbData and the size of the client read buffer is
specified by the cbAvailable value. The total number of bytes the client is going
to send is specified by the cbTotalBytes value.

If the cbTotalBytes value is equal to the cbAvailable value, then all the data
from the client has been read and there is no need to call ReadClient. If the
cbTotalBytes value is greater than the cbAvailable value, then you will need
to call ReadClient to make the Web server read more data from the client
browser.

The advantage to using multiple calls to ReadClient is related to Windows
CE memory constraints. You may want to use the Web Server to upload a
ten megabyte file to a flash card. You may have only two megabytes of RAM
available, but sufficient storage space is available on the card. If the
entire buffer from the client was read at once, the device would run out
of physical memory. However, if you use a 4 K buffer while calling ReadClient
and then call WriteFile immediately after each call, then you can minimize
the amount of RAM required.

If you use ISAPI ReadClient, you need to use caution when writing ISAPI
filters that receive notifications for read raw data events.

 
多人接受答案了。
 
to kyq,请来这里,我把其它分数给你。
http://www.delphibbs.com/delphibbs/dispq.asp?lid=786989

其余820分,我会回再开贴,一起给你的,,,
 
后退
顶部