Send small files from a Server (Lesson 3)

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.

Open Project

Open Project

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.

Drag one RtcDataProvider component to Form1

Drag one RtcDataProvider component to Form1

RtcDataServer Component on Form1

RtcDataServer Component on Form1

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.

Server Property for rdpFiles component

Server Property for rdpFiles component

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).

Check Order Property for rtdFiles component

Check Order Property for rtdFiles component

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?

  1. We declare a variable to store the root directory where our Files will be served.
  2. Extract the Path from our Application’s main executable file.
  3. Check that last character in our Path isn’t a “\” character.
  4. Add “\data” to our path so we will serve files only from this folder.
  5. 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.
  6. Add the File name to our path.
  7. 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”.

  1. We declare the vsFileName variable to hold the requester File Name.
  2. 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).
  3. Now we use our GetFullFileName function created in step 5.
  4. We are accepting anything that comes after http://localhost.
  5. 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?

  1. We are declaring two variables vsFileName and viFileSize, to get our File Name and our File Size
  2. We use our Sender as a RtcDataServer.
  3. 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.
  4. We check if the file exists with the File_Exists method from the rtcInfo unit.
  5. 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)
  6. If the Size of the file requested is less or equal to 2048 bytes then we send the requested file.
  7. If the Size is bigger than 2048 bytes we send an error indicating the size of the requested file.
  8. 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).

Data Directory inside Application's Exe Directory

Data Directory inside Application’s Exe Directory

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.

File In Data Directory

File In Data Directory

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.

Error when File Not Found

Error when File Not Found

Then we check what happens when the file is too big to be sent.

Error when File is too big

Error when File is too big

And last, we check the response when our file is found. This is a TXT file so the browser displays it’s content.

File Sent

File Sent

With this we finish our 3rd Demo. Next, we will see how to send big files when requested.

Files in this post.

  1. DEMO 3 Code – Sending small Files
  2. DEMO3 Sending Small File Size

3 thoughts on “Send small files from a Server (Lesson 3)

  1. Job Espejel

    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

    1. Jenaro Centeno Post author

      Job,

      The post is updated with your changes. Thanks.

  2. Pingback: RealThinClient SDK – Lesson 4 – Send large files out | RealThinClassroom

Comments are closed.