By this moment, we have been sending content generated by our Server. Now we are going to see how to send small files from a folder that resides inside our Server’s running directory. We’ll do it this way because with this approach we can control what files can be accessed from the Server.
We’ll use some functions to secure our Server and check that the content (file size in this case) is small enough to send.
In the next lesson we’ll see how to deal with bigger file sizes.
We’ll need the code of our Lesson 2b post which you can download at Code For RealThinClient SDK Lesson 2b.
Basically, we are going to:
- Open our Lesson 2b project.
- Add an RtcDataProvider component and set it’s properties.
- Create a function to check and return file location.
- Configure our RtcDataProvider OnCheckRequest and OnDataReceived events to serve the files.
- Create a folder in our Application’s running directory and add some files.
- Compile and run our project.
Steps.
1. Load our project from Lesson 2b.
2. Add an RtcDataProvider component to our Project.
We must add a new RtcDataProvider component to our Form1 in order to get any request that isn’t for rdpTime or rdpSquare components that we previously put in our project.
We rename our RtcDataProvider component to rdpFiles.
3. Set Server Property for our RtcDataProvider component.
As with our previous components, we must tell our new component which Server component will use to check for requests.
4. Set CheckOrder Property for RtcDataProvider component.
We must set CheckOrder property for rdpFiles component in order to make it the last to check the Request (OnCheckRequest event) from our RtcHttpServer1 component.
If we look at our previous components, both of them will have a value of 0 (zero) in their CheckOrder property. To be shure that our new RtcDataProvider component is the last one to check the request we set it’s CheckOrder to 900.
CheckOrder property is the Order in which the components will be asked to process a request. The smaller this Order number, the sooner a component will be asked to process a request, compared to other components connected to the same Server (more on this in next chapters).
5. Add a function to check for File location.
We are going to create a function to check the file location and if the file exists.
function TForm1.GetFullFileName(psFileName: string): string; var vsDocRoot : string; //(1) begin vsDocRoot := ExtractFilePath(ParamStr(0)); //(2) if Copy(vsDocRoot, Length(vsDocRoot), 1) = '\' then Delete(vsDocRoot, Length(vsDocRoot), 1); //(3) vsDocRoot := vsDocRoot + '\data'; //(4) psFileName := StringReplace(psFileName, '/', '\', [rfreplaceall]); //(5) psFileName := StringReplace(psFileName, '%20', ' ', [rfreplaceall]); Result := ExpandFileName(Trim(vsDocRoot) + Trim(psFileName)); //(6) if (AnsiPos('\..', Result) > 0) or //(7) (UpperCase(Copy(Result, 1, Length(vsDocRoot))) <> UpperCase(vsDocRoot)) then Result := ''; end;
What are we doing?
- We declare a variable to store the root directory where our Files will be served.
- Extract the Path from our Application’s main executable file.
- Check that last character in our Path isn’t a “\” character.
- Add “\data” to our path so we will serve files only from this folder.
- Replace all “/” characters for “\”. Remember, in Windows systems your path’s directories are separated with “\” characters, but in URL adress the “/” character is used as separator, so we have to change it.
- Add the File name to our path.
- If we have the “\..” our the path in our vsDocRoot variable is different to the path in our functions result then we send back an empty string.
6. Configure OnCheckRequest event for our RtcDataProvider component.
Next, we are configuring the OnCheckRequest event for our RtcDataProvider component.
procedure TForm1.rdpFilesCheckRequest(Sender: TRtcConnection); var vsFileName : string; //(1) begin with TRtcDataServer(Sender) do //(2) begin vsFileName := GetFullFileName(Request.FileName); //(3) Accept; Request.Info['FName'] := vsFileName; //(4) end; end;
What are we doing?
Remember that in step 4 we set our RtcDataProvider component’s CheckOrder property of 900? Well, what happens now is that the other two RtcDataProvider components have their CheckOrder property set to 0, so this two components will check the Request in first place, after they check the Request, our rdpFiles component will check the Request and take anything that is send except “/TIME” and “/SQUARE”.
- We declare the vsFileName variable to hold the requester File Name.
- As we are always doing, we use our object as TRtcDataServer for compatibility reasons (remember that this is with compatibility in mind because you may create ISAPI modules with RealThinClient components).
- Now we use our GetFullFileName function created in step 5.
- We are accepting anything that comes after http://localhost.
- After accepting the request we save the filename in our Request.Info[‘FName’] object property so we can use it later.
7. Configure OnDataReceived event for our RtcDataProvider component.
Once the Request has been accepted for our RtcDataProvider component, we proceed to see if we’ll send back a file of a message.
procedure TForm1.rdpFilesDataReceived(Sender: TRtcConnection); var vsFileName : string; //(1) viFileSize : integer; begin with TRtcDataServer(Sender) do //(2) if Request.Complete then begin vsFileName := Request.Info['FName']; //(3) if File_Exists(vsFileName) then //(4) begin viFileSize := File_Size(vsFileName); //(5) if (viFileSize <= 2048) then Write(Read_File(vsFileName)) //(6) else Write('File Too Long to be served: ' + IntToStr(viFileSize) + ' bytes'); //(7) end else Write('File not found on server: ' + Request.Info['FName']); //(8) end; end;
What are we doing?
- We are declaring two variables vsFileName and viFileSize, to get our File Name and our File Size
- We use our Sender as a RtcDataServer.
- Store our File Name in the vsFileName variable. Remember, in step 7 we set the value for Request.Info[‘FName’] object property. Now, we use it.
- We check if the file exists with the File_Exists method from the rtcInfo unit.
- Then, we use RTC’s SDK File_Size function to get the size of the file requested.(Check rtcInfo unit for more information on this)
- If the Size of the file requested is less or equal to 2048 bytes then we send the requested file.
- If the Size is bigger than 2048 bytes we send an error indicating the size of the requested file.
- If the requested file doesn’t exists then we send a message indicating that the requested file hasn’t been found in our server.
8. Create a Directory and add a few files into.
We must create a Directory to hold the files that we will send for the requests. This directory must be called “/data” (see step 5).
Next we may copy or create some files inside our “/data” Directory to be served. For the purpose of this example I’ve put two files in this directory, a TXT and an EXE file. The EXE file is bigger than 2048 bytes so we can see the File Size error.
9. Compile and Run our Project.
Compile and run the Project. First we’ll see what happens when there’s no file to be served.
Then we check what happens when the file is too big to be sent.
And last, we check the response when our file is found. This is a TXT file so the browser displays it’s content.
With this we finish our 3rd Demo. Next, we will see how to send big files when requested.
thanks
I’ll add to the GetFullFileName function
psFileName := StringReplace(psFileName, '/', '\', [rfreplaceall]); //(5)
psFileName := StringReplace(psFileName, '%20', ' ', [rfreplaceall]); // <----- new line to handle filename with spaces
Result := ExpandFileName(Trim(vsDocRoot) + Trim(psFileName)); //(6) <---- added trim
best regards
Job,
The post is updated with your changes. Thanks.
Pingback: RealThinClient SDK – Lesson 4 – Send large files out | RealThinClassroom