Cannot read the pdf content in the browser with ember - javascript

Objective: Display a pdf file, received as a response from server in the new window using ember.
Code in the route file:
actions: {
pdfClick(assessmentId) {
var result = [];
return new Ember.RSVP.Promise(function (resolve, reject) {
Ember.$.ajax({
type: 'GET',
url: 'http://localhost:4200/abc/secured/rest/questions/166',
success: function (data) {
var winlogicalname = "detailPDF";
var winparams = 'dependent=yes,locationbar=no,scrollbars=yes,menubar=yes,' +
'resizable,screenX=50,screenY=50,width=850,height=1050';
var detailWindow = window.open("content-type:application/pdf");
detailWindow.document.write(data);
},
error: function (request, textStatus, error) {
console.log(error);
}
});
});
}
}
Confusion:
var detailWindow = window.open("content-type:application/pdf");
detailWindow.document.write(data);
In the window.open, we are setting the content type as application/pdf and then when we try to write the data (bytestream of PDF file received as a response from the server), junk data appears in the new window.
If I hit the service by Chrome browser, Chrome is able to display the pdf but if I hit the same service with ember ajax, I am not able to display the pdf in the new window.

The problem is about jQuery. jQuery doesn't handle binary data (Reference). While your server is sending binary, you cannot handle this request.
You have different options:
Transporting the binary data by using base64 encryption: Actually I don't like it because of its' overhead.
Using pure XMLHttpRequest instead of jQuery: I've used this in my current project, it works! But too much line of code, hard to track and maintain. Need to wrap with Ember.Promise. My implementation is very close to these answers:1, 2.
Using jQuery transporters: I saw it but haven't use it yet. I don't know whether it is working or not. Here is the reference if you want to look it.

Related

Serializing DirectionsResult to JSON to send to my webservice not working fine

I am using the Google maps Javascript API and when the user changes the directions/route on the map (draggable is set to true) I want to send the new route/directionsResult to my webservice backend. The issue I am facing is when I serialize DirectionsResults using JSON.stringify I don't seem to be getting the full list of objects correctly converted to strings.
directionsDisplay.addListener('directions_changed', function () {
sendToBackendService(directionsDisplay.getDirections());
});
function sendToBackendService(result) {
var jsonToSend = JSON.stringify(result);
$.ajax({
type: 'POST',
url: './api/DirectionsUserModified',
data: jsonToSend,
error: processCallbackError,
success: function (apiJson) {
alert("post of new directions success");
}
});
}
The issue will always be related to the local environment of execution of your JavaScript code. So , the version of web browser you are using.
Maybe the object can't be serialized properly because the size limit is reached. The navigator uses the local storage as buffer during json serialization process. If the limit is reached, the String is simply truncated or an error is thrown.
You could have a look to this other post, maybe it'll help

Upload image by Froala to server with custom response format

I am using Froala editor.
I would like to upload images to own server, as described in documentation response format should be { link: 'path/to/image.jpg' }, but my server returns response with another format.
Is it possible to use custom response format with Froala, probably by handle some event?
there is nothing to do with the server response model via the front. its model is designed at backend and if you need to change it you maye parse the Json you get and change the model as you wish. to get the model exactly as you mentioned above you should talk to your backend team.
I'm using cloudinary.com for uploading and serving images and I also have no control on the response. My temporary solution was to monkey patch the JSON.parse method like this (coffeescript) :
var _parseJSON = JSON.parse;
JSON.parse = function(j) {
var response = _parseJSON(j);
response.link = response.secure_url;
return response;
};
I really hope to find a more elegant solution!
Froala seems to not have a mechanism to modify the response from the server when it manages uploads. There is a suitable froala event for this froalaEditor.file.uploaded, but it only can abort the upload process. May be in the future it will be updated to suit such cases
However what you want is absolutely doable. First you'll need to add a query param to imageUploadURL prop in your froala config, e.g. const froalaConfig = {imageUploadURL: '/yourUploadsEndpoint?fromFroala'}. This param is needed to distinguish requests that were actually made by froala from others.
Then we will do a little monkey patch to XMLHttpRequestObject, which is internally used by froala to make http requests:
const accessor = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'responseText')
Object.defineProperty(XMLHttpRequest.prototype, 'responseText', {
get() {
const responseText = accessor.get.call(this)
// here we can check if response url includes our previously set query param
if (this.responseURL.includes('?fromFroala')) {
// r is our response object
const r = JSON.parse(responseText)
return JSON.stringify({ link: <path to your uploaded image url here> })
}
return responseText
},
configurable: true,
})
This should do the trick until froala switches to another data fetching API.
The image.uploaded event is being triggered as soon as there is a response from the server. You could use the response parameter of this event together with the image.insert method to add the image in the editor.
Also, it is important to return false at the end of the callback to prevent the default editor upload chain.
Below is a code snippet for that:
$('.selector')
.froalaEditor()
.on('froalaEditor.image.uploaded', function (e, editor, response) {
// Parse response to get image url.
var img_url = ... ;
// Insert image.
editor.image.insert(img_url, false, null, editor.image.get(), response);
return false;
});

Reading a CSV file with jQuery

I have a downloaded CSV file which I would like to parse and use to create JSON objects for each record. The file is on my local machine but I have read that JavaScript has security measures in place that prevent access to these files.
Some examples show using csv.js with the following:
$.ajax({
url: "G:\downloaded_files\filename.csv",
aync: false,
success: function (csvd) {
csv_as_array = $.csv.toArrays(csvd);
},
dataType: "text",
complete: function () {
// use the array of arrays (variable csv_as_array)
// for further processing
}
});
When running this it just creates a GET request in the console. I am treading on unfamiliar territory here so any explanations would be great.
If I was to do this using Ruby I would do this, which hopefully will give you an indication of what I am trying to achieve:
require 'csv'
class FileRead
csv_text = File.read('/home/richardlewis/Downloads/csvtest.csv')
csv = CSV.parse(csv_text, headers: true)
csv.each do |row|
hash = row.to_hash
puts(hash)
end
end
I'm hoping this makes sense and someone can point me in the right direction.
You cannot call local files (from hard dics) using Ajax, or by any means from a web browser. You will have to publish your file using some sort of server. If you are using Linux you should have an Apache server already installed.
You need a REST service that will return your file in some format. JSON is the best, because it's easy to manipulate JSON data on the front-end.
It would look like this:
$.ajax({
url: "http://localhost:8080/services/rest/get_file", // your rest address
...
});

Return PDF to browser using JSON and MVC3

My requirement is whenever a Image is clicked a PDF should be opened on the browser. I am using Jquery ajax [POST call] to make a call to the ASP.NET MVC side and a file is returned on the response. A POST is required from the jquery side since I need to pass substantial data from client to server.
HTML Part:
<span data-id='printSettings' title='Generate PDF' class="preferenceSettings"></span>
JS Part: This is fired when the Generate PDF icon is clicked.
var textToSend = $('.microChartTable', self.element)[0];
var dataToSend = { htmlContent: textToSend.outerHTML };
$.ajax({
url: "/EADashboard/ConvertToPDF",
data: JSON.stringify(dataToSend),
type: 'POST',
contentType: 'application/json',
success: function (data) {
} // -- success ends here
});
ASP.NET Side : In my controller, I have the following code:
[HttpPost]
public FileResult ConvertToPDF(HtmContent content)
{
string fileName = Server.MapPath("~/SeedData/data.pdf");
string contentType = "application/pdf";
return new FilePathResult(fileName, contentType);
}
Now the PDF generation code is correct just that the PDF file is not been opened on the browser side. I have seen the post Return PDF to browser using JSON and MVC? but since there was no solution provided, I am posting this again. Can anyone let me know how this can be achieved ?
Thanks
Two things.
Why are you doing post via ajax and not a regular post? With a regular post your code would probably work.
If you indeed need to do it with ajax, you are receiving result in the data object on the success of the ajax call, and I do not see that you do anything with it, which is why you do not see anything happening.

Rendering mongodb database results from POST request in .ajax jquery wrapper in node js

I am creating a basic piece of functionality to allow users to send their location to a server which then queries a database and returns locations near to them. I am using the below jQuery .ajax wrapper to POST data to the server. This takes the form of a latlon point which is then used as the basis for a geosearch in MongoDB using nodejs and express on the backend. The results of the search are then intended to be returned to the client and rendered by the createMapListings function.
The /find page is initially rendered through a GET request to the database via mongodb separate from the below code. However subsequent to initial rendering, I then want to return results dependent on the location provided.
The POST method works fine and the location is posted to the server, with the search results being returned as I can print contents out through the console log.
However, I then want to render the results on the client-side. As mentioned, the results of the search render in the console, but when I attempt to pass through to the client, I can render the data itself (in the form of an array of objects) in the #output div, but the createMapListings function does not seem to catch the data.
In fact, the below function appears to be called but prints out over a thousand rows with the data that should be caught described as 'undefined'. I have tried to use res.render and res.redirect, but in the first case, the view renders in the div (which I suppose is expected) and the redirect fails.
The createMapListings function works fine when a simple GET request is made to the server, for example, for all objects in a collection, using ejs template. However, I think the issue here may be a combination of a POST request and then wanting to pass the results back to the AJAX request using the complete callback.
I apologise if the below code is somewhat obtuse. I’m definitely what you would call a beginner. I appreciate the above functionality may not possible so if there is a better way, I would of course be open to it (res.direct perhaps).
Here is the relevant client side script:
$(document).ready(function(){
$("#geolocate").click(function(){
navigator.geolocation.getCurrentPosition(geolocate, function(){
});
});
});
function geolocate(pos){
var latlonpt = [];
var x = pos.coords.latitude;
var y = pos.coords.longitude;
latlonpt.push(x);
latlonpt.push(y);
var obj = {
userlocation: latitudelongitudept
};
$.ajax({
url: "/find",
type: "POST",
contentType: "application/json",
processData: false,
data: JSON.stringify(obj),
complete: function (data) {
$('#output').html(data.responseText);
$('#infooutput').children().remove();
createMapListings(data.responseText);
}
});
};
function createMapListings(maps) {
for (var i = 0; i < maps.length; i++) {
var url = maps[i]._id;
var fullurl = "<a href='/show?id=" + url + "'>Route</a></div>";
var title = "<div>" + maps[i].title + " - " + fullurl +"";
$('#infooutput').append(title);
};
};
</script>
Here is the relevant route used in a basic express app to handle the post request made by the above .ajax wrapper.
exports.findbylocation = function(req, res) {
console.log(req.body.userlocation);
var userlocation = req.body.userlocation;
Map.ensureIndexes;
Map.find({loc :{ $near : userlocation }}, function(err, maps) {
if (err) {
console.log(err)
}
else {
var jmaps = JSON.stringify(maps);
console.log(jmaps);
res.send(jmaps);
}
});
};
By convention, the data variable name in an $.ajax callback signature refers to the parsed HTTP response body. Since your callback is on complete, we're actually passed the XMLHttpRequest used, by convention called xhr. You rightly grab the responseText property, but this needs parsing to be useful. So long as we take care over our Content-Type's and don't explicitly disable processData, jQuery will do the encoding/unencoding for us - we just deal with objects. This is a good thing, since the transport format isn't usually of any particular importance to the application logic. If we use res.json(maps) in place of res.send(jmaps), we can write our call more simply:
$.ajax({
url: '/find',
type: 'POST',
data: obj,
success: function(data) {},
error: function(xhr, text, err) {}
});
Here data is a Javascript object already parsed and ready to use. We also use a default application/x-www-form-urlencoded request rather than explicitly setting a contentType. This is the same as far as express is concerned: it will just be parsed by urlencoded instead of json.
Assuming you solved your client-sie problem.
As you are using express there is no need for JSON.stringfy,
you can use res.json(maps).

Categories

Resources