Document flow plays an important role in building a corporate system. The fp3 format is the main document of the finished report if you use FastReport VCL in your system.
To facilitate the generation of documents of different types from the internal format without rebuilding the reports, we have expanded our client-server components, which now enable to accept the fp3 format from clients and convert it to any available export format.
This is accompanied by a caching system where the server can refuse to accept its file and work with the cache. There are also minor settings, for example, the maximum size of the received file.
In order for your server to be able to receive and process fp3 files, you need to add a couple of settings to the config (XML file with settings).
HeaderMaxSize — the maximum size of the HTTP header in bytes. The maximum value is 16384.
ContentMaxSize — the maximum size of uploaded fp3 files in megabytes (0 — no limit).
We've also updated our demo projects, which you can download here.
On a client side, we will analyze PHP script in the role of a client, but, of course, a client can be written in any programming language.
HTML form for script:
<html> <head> <meta charset="utf-8"> </head> <body> <form enctype="multipart/form-data" action="post.php" method="POST"> <!-- MAX_FILE_SIZE must be specified before file upload field --> <input type="hidden" name="MAX_FILE_SIZE" value="3000000000" /> <!--The input element name defines the name in the array $_FILES --> Send this: <input name="userfile" type="file" /> <input type="submit" value="Send File" /> </form> </body> </html>
Post.php:
<?php //FastReport server address $host ='http://localhost:8097'; //Export format $exportFormat = 'PDF'; //The name of the file selected by the user $OldName = $_FILES['userfile']['name']; //Its actual name after our download (replace the tmp extension with fp3) $name = substr_replace($_FILES['userfile']['tmp_name'], 'fp3', -3); //Save on the php server move_uploaded_file($_FILES['userfile']['tmp_name'], $name); //Open it $file = new \CURLFile($name); //Initialize the cURL session $ch = curl_init(); //Install the downloadable url curl_setopt($ch, CURLOPT_URL, $host); //Choose a query method (Post) curl_setopt($ch, CURLOPT_POST, true); //To read the returned data curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //To read the returned header curl_setopt($ch, CURLOPT_HEADER, 1); //For large files, you need to increase the waiting time for sending (by default 30 seconds), set to 0, which means infinite waiting. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); //Generating MD5 for the file. $md5 = md5_file($name); //Sending format and MD5 curl_setopt($ch, CURLOPT_HTTPHEADER , array('Format-Export: '.$exportFormat, 'Content-MD5: '.$md5)); //Zip the file before sending $data = array($exportFormat => $file); //Sending the file curl_setopt($ch, CURLOPT_POSTFIELDS, $data); //Waiting for a response $response = curl_exec($ch); // Debug return check-out if (empty($response)) { echo 'received an empty response'; } else { if (strstr($response, 'HTTP/1.1 301') == '') { //Something went wrong. The server returned an unexpected response echo '404'; curl_close($ch); exit; } if (curl_errno($ch)) { //The server returned an error, which we display in red echo '<span style="color:red">'; echo 'error: '.curl_error($ch); echo '</span>'; } else { //Extract the address from the FastReport server response to receive export results $Location = GetLocationFromHeader($response); if (empty($Location)) { echo 'error: Location not found'; } else { //You can direct the client to the address to receive the file, but not in an architecture where the FastReport server
//is connected to the php server locally and does not have access to the Internet. You will have to download
//everything using the php server and it is safer from the point of view of logic in order to protect people's documents.
$file = file_get_contents_curl($host.$Location); if (empty($file)) { echo 'error: file missing'; } { //We need to generate a new name to return the file to the client. //Everything is implemented as follows: The file name is the same as that of the client,
//and the server response is analyzed to obtain the extension. //Let's extract the format from the response. We take the old name that the client sent us
//and replace the extension with the export result (if he sent 123.fp3, we will get 123.pdf). $Format = getExtension(GetFileNameFromLocation($Location)); $OldName = substr_replace($OldName, $Format, -3); //Transferring files from the php server to the client header('X-Accel-Redirect: storage/'.$OldName); header('Content-Disposition: attachment; filename="'.$OldName.'"'); echo $file; } } } } curl_close($ch); //Secondary functions //Extracts the address from the server response to get the conversion result function GetLocationFromHeader($arg_1) { $Location = strstr($arg_1, 'Location'); $Location = strstr($Location, '/'); $Location = substr($Location, 0, strrpos($Location, 'SessionId')-2); return $Location; } //Getting filename from response function GetFileNameFromLocation($arg_1) { $FN = substr($arg_1, strripos($arg_1, '/')+1, strlen($arg_1)); return $FN; } //Getting extension from filename function getExtension($fileName) { return substr($fileName, strrpos($fileName, '.') + 1); } //Faster function counterpart file_get_contents function file_get_contents_curl($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); $data = curl_exec($ch); curl_close($ch); return $data; } ?>
This way you can get rid of several big problems. You won’t need to rebuild reports, which reduces the load on the server. Reports can be stored in any convenient place, and the client side can be written in any programming language that is comfortable for you.