How to get a PDF from Server Side to Client Side?

So you generate a PDF in the C# code or any back end code, but need to send it back to the JavaScript doing the AJAX request. The trouble is how do you return a file back to the client side, which is the same problem I faced. There are loads of methods of how to do this that I have seen on the line, but these are the ways I found worked with C#.NET and JavaScript consistently.

Returning the File

First method I found was very simple and the most direct route to the user. In this scenario you do an AJAX request from the JavaScript straight to the back end system that is generating the PDF file and return that file in the request.

First get the file from the file system into a ‘FileStream’:

Var filesFullPath = "C:\documents\pdfDocument.pdf";
Var fileStream = new FileStream(filesFullPath , FileMode.Open, FileAccess.Read, FileShare.Delete, 4096, fileOptions);

Then use the ‘ControllerBase.File’ class, part of the Controllers inherited class, to convert the ‘FileStream’ into a ‘FileResult’ with a PDF content Type:

Var fileResult = ControllerBase.File(fileStream, "application/pdf");

‘ControllerBase’ is part of the inherited ‘Controller’ Class from ‘Microsoft.AspNetCore.Mvc’.

You can then return this object back to the requesting JavaScript. On the client side it is just a standard ‘XMLHttpRequest’, but the key part is the ‘responseType’ is set to ‘arrayBuffer’.

This means when the response comes back in that format we can create a new ‘Blob’ from the object with the correct content type. This Blob is then converted to a URL and opened in a new window.

var url = "<a href="http://www.GetMyPdf.com/GetPdf">http://www.GetMyPdf.com/GetPdf</a>";

// Send Request
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.responseType = 'arraybuffer';
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onload = function (e) {

// Check status
if (this.status == 200) {

// convert response to Blob, then create URL from blob.
var blob = new Blob([this.response], { type: 'application/pdf' }),
fileURL = URL.createObjectURL(blob);

// open new URL
window.open(fileURL, '_blank');

} else {

console.error('response: ', this);

}
};

xhr.send(JSON.stringify(data));

Now this works great in the scenario above, but a situation that we came against was the back end code to the client side was not doing the generating there was a middle tier, then also it was handling the response from all APIs as a json response which is a string type. Therefore we couldn’t return the file directly and not in an Array Buffer format.

A better solution would be to store the PDF file somewhere the client side can request it after it has been generated. This will save on the large packet of data being sent back and less worry of data loss, but let us continue on this path anyway.

The solution to the weird request is to use Base64 as the string based response. In the C# code we can convert the file into ‘bytes’, which can then be converted to Base64 string:

var fileFullPath = "C:\documents\MyPdf.pdf";

// Convert to Bytes Array
bytes[] pdfBytes = File.ReadAllBytes(fileFullPath );

// Convert to Base64
var base64Str = Convert.ToBase64String(pdfBytes);

This is then saved to return back as a string to the middle tier and then back to the client side.

We now have a string response that we can to convert the Baset64 into a PDF file for the client, which can work both of these ways.

If you first prefix the Base64 with the PDF Base64 DataURI as below:

var base64Str = "****";
var base64DataUri = 'data:application/pdf;base64,' + base64Str;

You can then open the Data URI in a window:

// open new URL
window.open(base64DataUri , '_blank');

However I didn’t find this consistently working, so instead I do the same as before with the ‘XMLHttpRequest’, but instead the URL is the Data URI.

var url = base64DataUri;

// Send Request
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.responseType = 'arraybuffer';
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onload = function (e) {

// Check status
if (this.status == 200) {
// convert response to Blob, then create URL from blob.
var blob = new Blob([this.response], { type: 'application/pdf' }),
fileURL = URL.createObjectURL(blob);

// open new URL
window.open(fileURL, '_blank');

} else {

console.error('response: ', this);
}
};

xhr.send();

This now uses the base64 string as the URL to request the PDF as a web request so we can return the PDF as a Byte Array, then just like before it is converted to a Blob, to URL and opened in a new window.

So far this has worked and consistently, so try it out and give me any feedback.

Keeping an images ratio on resize in JavaScript

A little tricky task was given to the team I am working in, to keep an image at its aspect ratio. However the catch is that it needs to be able to go as large as it can to fill the screen at all times, while the user can resize the screen and keeping the images size ratio. Easy you may say, but once you get into it, not so much.

Three of us thought long and hard through many different situation of how we can calculate the size, detect the users actions and calculate the ratio, but with no luck. We also then hunted the internet as all great developers do, which produced many methods using some very long calculation, but none just seemed to work and we knew nothing about the maths.

Then like a shine of light I thought of how you can do it in a simple way. Instead of thinking of the image at 1980px by 1020px and then calculate out the pixel difference etc, you need to think about the image in percentages. When you reduce the images width by say 594 pixel, you would then think of how to calculate the relative pixel difference on the height of the image, but this would be going in the realms of mathematicians. Therefore you stop thinking of that in pixels and think that 1980px reduced by 594px, is a 30% reduction.

Now all you need to do is reduce the height also by 30%, relative to the heights pixels, so here we go…

First we need to find out what the width and heights relative 1% is, so we know where to work from. You need to provide the images original height and width to start this off, then divide each by 100, simple maths.

// Get the one percent of the image width and height
var widthOnePercent = imageOriginWidth / 100;
var heightOnePercent = imageOriginHeight / 100;

Next because we want the image to be as large as it can, we will set the width to be as large as the container to start off the calculations. Once this has been set we can use the images size to find out what percentage the width is at. We know the width of what the image is at in pixels and we know how many pixels are 1%, therefore we can divide the images width by 1%. For example 1386px divided by 19.8px equals 70%.

// Calculate the width percentage
var imageCurrentWidth = $(imageSelector).width();
var imageCurrentPercent = imageCurrentWidth / widthOnePercent;

Now we just need to set the height of the image to 70% of the images height, by multiplying the images 1% height by 70%.

// Calculate the height relative to the percentage of the images width
var imageNewHeight = heightOnePercent * imageCurrentPercent;

However this will work to put the image within the width boundary of the container and the images ratio kept in tact, but potentially due to the width the height could be off the screen. Therefore we need to make sure the image doesn’t go off the screen. This can be calculated out by checking if the height of the image, plus the distance from the top of the window, is not as large as the windows height.

($(window).height() < $(imageSelector).offset().top + imageNewHeight)

Once we have determined this, then we do the same as before but in the opposite direction. This time we start with what height we want the image to be, instead of what height it is. To do this we use the windows height, minus the images top offset, which gives use what space is left.

// Set the new height so it fit on the screen
imageNewHeight = $(window).height() - $(imageSelector).offset().top;

Then the same as before, it is divided by the images 1% height to calculate what the percentage the width is going to be.

// Calculate out what percentage is the height at
imageCurrentPercent = imageNewHeight / heightOnePercent;

// Calculate the width relative to the percentage of the images height
var imageNewWidth = widthOnePercent * imageCurrentPercent;

Below is the full JavaScript code, but to see a full example check out my PureRandom CodePen.

(function($) {

function calIamgeSize(imageSelector, imageOriginWidth, imageOriginHeight) {

// make image as big as it can to start
$(imageSelector).width(
$(imageSelector).parent().width()
);

// Get the one percent of the image width and height
var widthOnePercent = imageOriginWidth / 100;
var heightOnePercent = imageOriginHeight / 100;

// Calculate the width percentage
var imageCurrentWidth = $(imageSelector).width();
var imageCurrentPercent = imageCurrentWidth / widthOnePercent;

// Calculate the height relative to the percentage of the images width
var imageNewHeight = heightOnePercent * imageCurrentPercent;

// If the images height is off the page, then rescale
if ($(window).height() < $(imageSelector).offset().top + imageNewHeight) {

// Set the new height so it fit on the screen
imageNewHeight = $(window).height() - $(imageSelector).offset().top;

// Calculate out what percentage is the height at
imageCurrentPercent = imageNewHeight / heightOnePercent;

// Calculate the width relative to the percentage of the images height
var imageNewWidth = widthOnePercent * imageCurrentPercent;

// Set new width of image
$(imageSelector).width(imageNewWidth);

}

// set new height of image
$(imageSelector).height(imageNewHeight);

}

// Resize image
var imageW = 1000;
var imageH = 667;
var imageClass = ".js-render-image";

$(window).on("resize", function() {

calIamgeSize(imageClass, imageW, imageH);

});

calIamgeSize(imageClass, imageW, imageH);

})($);

How to Iterate multiple folders/files in Gulp

When searching for a method to loop not just the first level of files and folders, but also all the levels below. Asking to much I wanted the files name, its folder location and also the files content. I found it…

I found the Gulp plugin ‘src’ and ‘tap’…

To use the gulp-tap simply use the command ‘gulp’, use the ‘src’ property with wildcards for the folders/files and then add the ‘tap’ property on.

The ‘src’ is the part that gets the collection of the files and the folders, which can be direct to a file or using the wildcards you can iterate through the folders to multiple levels. There is then further conditional methods to filter the files and their types.

The ‘tap’ then taps into each of the returned items with its details. I was looking for the files path, name and the content, but the file object has much more to offer.

gulp.src("src/**/*.{json,config}")    .pipe(tap(function(file, t) {        // Files path and name e.g. src/folder/folder/package.json        var FilePathAndName = file.path;        // File path using the above to trim off the name
        Var FilePath = FilePathAndName.substring(0,FilePathAndName.lastIndexOf('\\');        // File name using the above to trim off the path
        Var FileName = FilePathAndName.substring(FilePathAndName.lastIndexOf('\\');        // Content of the file in string format
        Var FileContent = file.content;    }))Don’t forget to add the name into the package.json and the require command at the top of the JavaScript file as per the links below.

Gulp for Beginners > https://quangphamsoft.wordpress.com/2017/02/10/gulp-for-beginners/