翻譯|使用教程|編輯:況魚杰|2019-07-30 16:53:09.013|閱讀 193 次
概述:本教程將會介紹創建一個能夠發送文件的Web服務器,無論其大小如何。在此過程中,我們必須小心服務器的內存,服務器內中可能有一個非常大的文件,不需要因為這個文件把所有的內存都占用了。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
RealThinClient SDK是用于開發標準的HTTP(S)服務器,ISAPI擴展以及客戶端的VCL控件。可用于Windows下的CodeGear Delphi 6-2010。關于RealThinClient SDK的教程會持續更新,本節是RealThinClient SDK的第四課,如何從服務器發送小文件。
本教程將會介紹創建一個能夠發送文件的Web服務器,無論其大小如何。在此過程中,我們必須小心服務器的內存,服務器內中可能有一個非常大的文件,不需要因為這個文件把所有的內存都占用了。
在前兩個示例中,我們一直在RtcDataProvider組件的OnCheckRequest和OnDataReceived事件上發送所有內容。現在,為了能夠發送大內容(大文件),除了我們從RtcDataProvider組件使用的事件之外,我們還需要OnDataSent事件。在先前調用Write函數準備的所有數據都已發送到客戶端并且所有發送緩沖區都為空之后,將調用此事件。另外,我們需要對TRtcDataServer的Response屬性進行一些檢查。
我們將使用第4課(感興趣的用戶也可以查看一下)開發的代碼作為基礎,就能夠從我們的服務器發送大文件。我們為每個單個事件調用定義了16K的內存限制,以便為從我們的服務器請求文件的任何客戶端保持服務器的內存使用率低至16K。
接下來看看具體的步驟:
打開我們的第4課代碼。
更改我們的RtcDataProvider的OnCheckRequest事件。
我們將更改最后一個RtcDataProvider組件的OnCheckRequest事件,將Response.ContentLength值設置為文件大小。為此,請雙擊最后一個RtcDataProvider組件以跳轉到OnCheckRequest事件。事件只有一小部分,但為了將它們保存在一個地方,這里是完整的新事件實現的代碼:
procedure TForm1.rdpFilesCheckRequest(Sender: TRtcConnection); var vsFileName : string; begin with TRtcDataServer(Sender) do begin vsFileName := GetFullFileName(Request.FileName); //(1) Accept; Request.Info['FName'] := vsFileName; Response.ContentLength:=File_Size(vsFileName);//(2) WriteHeader;//(3) end; end;
我們在做什么?
正如在演示3中所做的那樣,將文件名存儲在請求中,這樣不必在以后再次重新創建它。
需要設置Response.ContentLength,告訴RtcDataServer我們響應中的內容(數據)有多大。如果不設置Response.ContentLength,RtcDataServer將假定調用Write的第一個事件來響應,并將計算ContentLength。
發送響應標頭,這樣就不必在文件大小為零的情況下調用Write。
更改我們的RtcDataProvider的OnDataReceived事件。
現在,我們將更新OnDataReceived我們的事件RtcDataProvider,為了只發送有限的數據量(我們設定該限制到16KB)。
procedure TForm1.rdpFilesDataReceived(Sender: TRtcConnection); var vsFileName : string; viSent : integer; begin with TRtcDataServer(Sender) do if Request.Complete then begin if Response.ContentLength > Response.ContentOut then //(1) begin vsFileName := Request.Info['FName']; if File_Exists(vsFileName) then begin if File_Size(vsFileName) = Response.ContentLength then //(2) begin viSent := Response.ContentLength - Response.ContentOut; //(3) if viSent > 16000 then viSent := 16000; //(4) Write(Read_File(vsFileName, Response.ContentOut, viSent) ); //(5) end else Disconnect; //(6) end else Write('File not found on server: ' + vsFileName); //(7) end; end; end;
我們在做什么?
檢查是否必須發送更多數據。
僅在文件大小未更改時才繼續,否則則斷開連接。
計算仍然需要發送的文件內容大小。
限制一次發送為16KB的長度。
從文件(vsFileName)中發送viSent字節,從位置Response.ContentOut開始。
斷開客戶端,因為文件已經更改,不斷開將會發送錯誤的標題和文件。
如果找不到文件,則會向客戶端發送錯誤消息。
在OnDataSent事件中實現OnDataReceived事件。
必須為OnDataSent事件實現OnDataReceived事件。如果不這樣做,那么我們的服務器將只發送Header和第一個16K的數據,并且轉移永遠不會結束。
編譯并運行項目。
現在可以編譯并運行項目了。請記住,您可以將任何大文件放在data子目錄中,它將僅使用16K而不是整個服務器的內存。
關注慧聚IT微信公眾號 ???,了解產品的最新動態及最新資訊。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自: