LoadRunner VuGen scripting - How to automatically download file from server and save it to local disk?

LoadRunner VuGen scripting - How to automatically download file from server and save it to local disk?


In my previous article, "How to record a file saving, performed by user from browser page?", I shown that user's activities are not recorded by LoadRunner. This is a rule!

LoadRunner records file transferring from server and does not record file saving.

What to do, if you have to save transferred file to local disk?
Continue reading, and you will get the solution :)

So, Let's start.
You can download file from a server with the web_url function.
See an example:

Image downloading:
  1. web_url("logo.gif",
  2.     "URL=http://www.google.com/intl/en_ALL/images/logo.gif",
  3.     "Resource=1",
  4.     "RecContentType=image/gif",
  5.     "Snapshot=t1.inf",
  6.     LAST);



This code downloads Google's logo image:

To save this image as file to local disk, we have to perform these steps:
  1. Capture image from server's response
  2. Save captured data to local disk

How to capture image from server's response?

Use web_reg_save_param function with the following boundaries - "LB=\r\n\r\n", "RB=". These boundaries allows to capture the whole data from a body of server's response. Function will look like:
    web_reg_save_param("prmLogoImage", "LB=\r\n\r\n", "RB=", LAST);

This function should be placed before web_url function. After execution, prmLogoImage parameter will contain GIF-file.

I will clarify briefly the meaning of boundaries - "LB=\r\n\r\n" and "RB=".
Please, read the basic concepts of HTTP protocol, read Request message section:

HTTP response consists of the following:
  • Headers, such as HTTP/1.1 200 OK or Content-Length: 3473
  • An empty line
  • A message body, containg text of requested page or file
So, Header and Message body should be separated by empty line.
First CRLF (that is, a carriage return (CR = "\r") followed by a line feed (LF = "\n")) ends last header, and second CRLF ( = "\r\n") creates empty line. All data, followed by second CRLF, are treated as message body.
To summurize - "LB=\r\n\r\n" says "start capturing from the beginning of message body", empty right boundary "RB=" says "capture data till the end of message".

Open LoadRunner and enable logging of data, returned by server:

Then execute script containing initial web_url function, and open Replay log:
As you see, Replay log contains "\r\n\r\n" at the end of server's response.
Also, pay attention, that server returns the length of file to be downloaded (Content-Length: 8558).


Save captured data to local disk
Saving captured binary data (in our case, GIF file) requires additional step - we have to determine the length (= size) of captured data.

Tips: The simplest way - strlen function - is not correct. Imagine, that that captured data contains embedded NULL characters ('\0'):
"123\0qwe"
The real size of captured data = 7 bytes ('1', '2', '3', '\0', 'q', 'w', 'e').
But strlen function will return value 3, because it counts bytes before the first NULL character ('\0').

To calculate size of captured data use lr_eval_string_ext function:
    lr_eval_string_ext ("{prmLogoImage}", strlen("{prmLogoImage}") /* = 14*/, &szBuf, &nLength, 0, 0,-1);

lr_eval_string_ext function copies captured data into szBuf array and places a size of captured data into nLength variable. That's easy, I hope :) If not, Help will help :)

Tips: There is another way to get known the size of file to be downloaded. Remember, that server returned the length of file (Content-Length: 8558). So, you can extract this value using Correlation.


And the last action is to save binary data from szBuf array into a local file. I used standard fwrite function from C programming language:
    fwrite(szBuf, len, 1, hFile);

Well, please see the whole source code:

Click the block to expand the source code:
  1. int WriteDataToFile(char *szFileName, const char *szBuf, int len)
  2. {
  3.     int hFile;

  4.     hFile = fopen(szFileName,"wb");
  5. .....


Execute the source code, and you will see, that new file will be created and saved automatically - "C:\LogoImage.gif". And this is what we needed - Google's logo image.

18 comments:

Hs said...

Hi Dmitry, thanks for visiting my site! :) I like your site alot! It's a great site as there are many detail examples on the scripting related issues that my site is lacking and some tips on working with the scripts. :) Hope we can share our experiences together in future too. :)

Hs said...

Btw, I've linked your site for the convenience of anyone seeking for scripting tips. :) Hope you wouldn't mind. :)

. said...

Really nice posts. Examples are very good.

Dmitry Motevich said...

Hs and PagKis.com,
Thank you for your opinions! :)
I'm glad that you like this site.

positivethinking said...

Hello!

First many thanks for visting my site and gave your valuable comments...

Im Happy to receive ur comments

Unknown said...

Hey The code was really helpful.. Can v paramertize the path to download many files.if yes pls suggest

Unknown said...

Hi... How can i load test microsooft web Outlook... i have tried it but it fails.. plss help me

K CS Anjaneyulu said...

hi..can any one tell me how to handle popup's in load runner....
while executing the scenario, i'm getting the security alert popup with "YES" or "NO" buttons....when i run in Internet Explorer....
For this, my script is getting failed...

Suvarna said...

Ver Nice tip....
LB=\r\n\r\n..it works and the excel file gets downloaded very much fine.

Thanks for the tip....:)

Sachin Wagh said...

Hi,

Very informative blog. I have a query related to this blog. The web page computes something and then displays the value in one of the text boxes. I intend to capture that value and push it in a text file. Can you please let me know if there is a way of doing the same?

Dmitry Motevich said...

Sachin,
It's important to know where the value is generated.

There are two cases:

1. Value is generates on server (server returns this value in his response).
In this case you should use correlation. Please, search my blog for 'correlation' and you'll find several visual tutorials.

2. Value is generated on client side (for example, JavaScript calculates it).
In this case you should simulate JavaScript code in your VuGen script. So, LoadRunner script will calculate the same value as JavaScript. And you'll be able to use the calculated value later in your script.

Anonymous said...

Please help,
i am running Vugen 9.1 on a .net 3.5 platform using web_Click_and_script protocol. I want to send in some data into the server, but all i get is webcustom request with body binary code that looks like this
web_custom_request("rmtre.dll_54",
"URL=http://tc6260-n1/epower/rmtre.dll?10.
"BodyBinary=s\\x02\\x00\\x10x\\x9C\\x95R\\xC1N\\x83@\\x10}\\x145\\x8D\\xD6\\x83\\x9E=\\x90\\x9E4\\xDA\\xA6\\x05\\xA2\\xC5\\x13\\xB5\\xD0\\xC4C\\x0F\\

when i try to pull out data using web_set_max_html_param_len("5000");

web_reg_save_param("d","Search=Body", "ORD=ALL","LB/BIN=\\xF7", "RB/BIN=\\x99+", LAST);
it gives me this error:
Action.c(793): Error -26377: No match found for the requested parameter "d". Check whether the requested boundaries exist in the response data. Also, if the data you want to save exceeds 5000 bytes, use web_set_max_html_param_len to increase the parameter size [MsgId: MERR-26377]
Action.c(793): Notify: Saving Parameter "d_count = 0"
Action.c(793): web_custom_request("rmtre.dll_54") highest severity level was "ERROR", 733 body bytes, 154 header bytes [MsgId: MMSG-26388]
please reply to 90percentile@gmail.com if you have a solution

Dmitry Motevich said...

Anonymous (September 11),
I think, the error messages is clear enough:
Check whether the requested boundaries exist in the response data. Also, if the data you want to save exceeds 5000 bytes, use web_set_max_html_param_len to increase the parameter size.
Please, answer - did you try these actions? What was the result?

Unknown said...

Hi Dmitry,

This post was really helpful, can we download multiple files at time by simulating number of users in controller? If yes, how can we achive this?

Please help me out here.

Dmitry Motevich said...

to Niranjan (September 16),
Yes, sure.
All you need is:
1. Generate a unique file name for each downloaded file
I posted on my blog two ways how to do that.
2. Star a required number of VUsers in LR Controller. Each VUser will download and save file in parallel.

Unknown said...

Hi Dmitry,
I tried my best but could not get any information about the response data, so could not do much. I am waiting for Vugen for .NET 3.5 which will be out with the new launch of Vugen.

Anonymous said...

Hi Dmitry,
Its very useful. But am facing a situation in which the a popup is getting displayed with a status msg saying(50 of 1000 downloaded etc) after clicking the download button. So the recorded script includes some thinktime in the script. if i remove them its not working.
These recorded statements are repeated web _submit_data statements that says unsynchronized servlet in the url.
even i try to put them in the loop and try to correlate by fetching the 'content length' and compare that with the file size length. but that doesnt seem to work all the time. what will be the solution to this? even the extended log of the server is repeating the download msg for the calls like

Downloading+page+1000+1000\n
Downloading+page+1000+1000\n
Downloading+page+1000+1000\n
Downloading+page+1000+1000\n
Downloading+page+1000+1000\n
so how to make the logic work?

Thanks.

Dmitry Motevich said...

@Kalyani,
Sorry,
I'm afraid, I cannot help you because you didn't didn't provide detailed information about your issue.