Node.js / Express : download file via ajax - javascript

I am trying to dynamically request a file for download via a GET ajax call. I have the following client-side code:
$(function() {
$('#submit').click(function() {
$.ajax({
type: "GET",
url: "/download/" + "filename",
dataType: "json",
contentType: "application/json",
complete: function() {
console.log('Complete');
},
success: function() {
console.log('Success');
},
error: function() {
console.log('Error');
}
});
});
});
On the node server I also have the following line (mind you, I have no idea if this is the correct way to do this)
app.get('/download/:filename', function(req, res) {
console.log(req.params);
res.write(fs.readFileSync(__dirname + "/../public/javascripts/main.js", 'utf8'));
});
So I want to actually download that javascript file (eventually dynamically). How would I go about doing this correctly? Something tells me I need to be specifying the headers / content type.

You should return with the content type and disposition set to:
Content-Type: application/octet-stream
Content-Disposition: attachment;filename=\"main.js\"
I believe you'll have to redirect to this file though. If I'm not mistaken, you can't force a file download via an AJAX call.

Is your intent to have the .js file interpreted and applied to the downloading page?
If so you would probably end up using write() to page, no matter how you GET it, and this would not be best-practice.
Instead check out require.js. This is a better way to asynchronously and dynamically load scripts, and apply them at runtime.
One difficulty that you would encounter in downloading dynamic .js files, with a manual solution, is dependencies. On .js file dependent on another would result in blind js undefined errors.
Plus, there is a runtime performance optimization gain in converting synchronous included files to asynchronous included files.
Require.js solves for these nicely.
Hope that helps.
All the best!
Clint

Related

How to get data from local JSON using Ajax?

Hello brilliant people!
I've been sitting hours trying to figure out why I cant load a local JSON file using Ajax. I bet it's some silly typo, of that I totally misunderstand something. I'm using Node.js Express.
The location of the two files:
"trollytrains/views/trips.ejs" (Doing the ajax-request)
"trollytrains/json/allstops.json"
$.ajax(
{
type: "GET",
url: "../json/allstops.json",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
alert('success');
},
error: function (msg) {
alert("error");
alert(msg.responseText);
}
});
I have tried altering the URL in all kinds of variations:
./allstops.json
allstops.json
json/allstops
/json/allstops
/json.allstops.json
No matter what I type I get a 404 error.
GET http://localhost:1337/json/allstops.json 404 (Not Found) jquery.min.js:4
Am I entering the wrong URL, or is there some other problem in my code that I haven't detected? I'm very new to JSON and Javascript so I wouln't be surprised.
I'd really appreciate some tips!
Best
/ J
Am I entering the wrong URL, or is there some other problem in my code that I haven't detected?
It depends on whether you can access the URL in the request in your example:
GET http://localhost:1337/json/allstops.json 404 (Not Found) jquery.min.js:4
See if you see the correct JSON when you go to http://localhost:1337/json/allstops.json with the browser. If you get 404 then this JSON is not served at this PATH and the problem can be either your backend failing to serve the JSON or you using the wrong URL.
It's impossible to tell you if you backend code is fine if you didn't include even a single line of the code that actually attempts to serve the JSON in question.
My assumption would be that you're not serving the JSON files.
I assume that you entire app is located in trollytrains directory and you have a json directory inside. To serve what's there you need to use something like this if you're using Express:
app.use('/json', express.static(path.join(__dirname, 'json')));
For more options to serve static files with and without Express, see this answer:
How to serve an image using nodejs
Try this.
$.ajax({
url: '../json/allstops.json',
dataType: 'json',
data:
async: false,
success:function()
{}
});

Get proper root in javascript file

I'm having a problem with resolving the root of a URL between my local machine and after deploying an application on IIS to our dev server.
The url when running locally is something like this.
http://localhost:57173/
the url when running on the dev server is something like this.
http://ServerName/AppName
I have JQuery Ajax calls to a web api and it won't find the location on the dev server if the trailing slash is left off.
Here's the call
$.ajax({
type: "GET",
url: "api/MyApi/Get",
data: { period: selectedPeriod },
cache: false,
success: function (data) {
}
});
If I look in FireBug at the api call on the dev server, with the trailing slash left off, it will show
http://ServerName/api/MyApi/Get
If I do have the trailing slash, it will resolve correctly to this. (Notice the AppName now included.)
http://ServerName/AppName/api/MyApi/Get
What am I missing here? It looks like it's not finding the proper root of the application when I move it to this server. The trailing slash makes no difference locally. It will find the api either way. Any ideas how to resolve this?
I also had this issue, the way to solved it was declare a javascript variable that contains the part of the url that differs in both environments (dev and local) and prepend that to every ajax request:
I put that variable in the layout file (Views/Shared/_Layout.cshtml), so that it could be automatically filled by ASP.NET and then used globally (make sure to create the script before the #RenderSection call):
...
<script>
var baseUrl = #Html.Raw(Json.Encode(Url.Content("~")));
</sctipt>
#RenderSection("scripts", required: false)
</body>
...
Then prepend that variable in the url of the ajax call (for example View/Home/Index.cshtml):
#section scripts {
$.ajax({
type: "GET",
url: baseUrl + "api/MyApi/Get",
data: { period: selectedPeriod },
cache: false,
success: function (data) {}
});
}
A url without a leading slash is considered a relative url. Your url "api/MyApi/Get" will be resolved by the browser relative to the url of the page containing the script.
http://ServerName/AppName appears to the browser as if it is a page request, with AppName being the name of the page and the AppName is not considered when resolving the url.
http://ServerName/AppName/ (trailing slash) appears to the browser as a directory request and becomes the base of your relative url.
The best fix for this is probably to redirect requests for http://ServerName/AppName to http://ServerName/AppName/
To do the redirect from within your application, insert the following into your /Home/Index controller action (before any other code)
if (!Request.Url.AbsolutePath.EndsWith("/"))
{
return Redirect("~/");
}
This will redirect any request for http://ServerName/AppName to http://ServerName/AppName/ As a side effect, it would also redirect any requests for http://ServerName/AppName/Index to http://ServerName/AppName/ but I don't think that would cause you any problems.
Javascript typically doesn't run unless the user causes an event to occur. I prefer to use the following because it allows MVC to get the exact route properly everytime no matter where you deploy.
Html
<button data-url="#Url.Action("MyApi", "Get")"></button>
Javascript
$(document).ready(function()
{
$('button').on('click', function()
{
var url = $(this).data('url');
$.ajax({
type: "GET",
url: url,
data: { period: selectedPeriod },
cache: false,
success: function (data) {
});
});
});
Hard coding a url in javascript I consider bad-practice.

Content-Type Ajax json missing

I wrote some php code that outputs some valid json, and sets the content-type header to application/json in my dev setup. However when I deploy this script to a embedded webserver it works fine except it's not capable of sending the content-type. It's not possible to run a other webserver.
Now I have the following code for Dynatable. Even though my dev and my embedded webserver, serve exactly the same file, and the only difference is the content-type. It works for my dev setup, however it doesn't work for my embedded setup.
I use the following code to load the json file to dynatable.
document.ready(
$.ajax({
url: 'phpApi.php',
success: function(data){
$('#myTable').dynatable({
dataset: {
records: data
}
});
}
}));
So can someone explain me why the content-type is so important for ajax? How can I tell my code manually its json?
Without the content-type the returned data is assumed to be plain text. There is nothing in your code to tell it otherwise.
One way to get json would be to specify the return type in the jquery code. Just add dataType: 'json' into the ajax configuration.
Or you could use eval() to transform the returned text to json.
document.ready(
$.ajax({
url: 'phpApi.php',
success: function(data){
$('#myTable').dynatable({
dataset: {
records: eval(data)
}
});
}
}));
Using JSON.stringify(eval(data)) might give you better results by making sure its json.
As pointed out below, JSON.parse(data) would probably be safer. (Eval is evil after all.)
So can someone explain me why the content-type is so important for ajax?
It's important so the client can identify what type of content the server returned, content-type: application/json tells jQUery to parse the data as an object. If no content type is returned, the client will assume the returned data is just plain text.
How can I tell my code manually its json?
Add dataType: "json" parameter to $.ajax()
document.ready(
$.ajax({
url: 'phpApi.php',
dataType: "json",
success: function(data){
$('#myTable').dynatable({
dataset: {
records: data
}
});
}
}));

Calling a Python script from Javascript, both local files

I'm trying to run a python script from a local javascript file (part of a locally running HTML/javascript program).
I've been googling this for hours and found a lot of solutions, none of which actually work for me.
Here is the javascript:
$.ajax({
type: "POST",
url: "test.py",
data: { param: " "}
}).done(function( o ) {
alert("OK");
});
The test.py file is in the same folder as the script/html file.
here is the script:
#!/usr/bin/python
import os
filepath = os.getcwd()
def MakeFile(file_name):
temp_path = filepath + file_name
with open(file_name, 'w') as f:
f.write('''\
def print_success():
print "sucesss"
''')
print 'Execution completed.'
MakeFile("bla.txt");
It works fine when run normally.
On my Firefox console I get a "not well formed" error and the script doesn't create a file. However, I can see that Firefox does fetch the script, as I can view it in my browser by clicking the file name.
In order for the python script to execute it has to be deployed by a web server that supports it via CGI or WSGI, etc.
Check out the docs here: webservers
There are three problems with your code.
First, when you call $.ajax(), it tries to parse the response as either JSON or HTML. To prevent it, use dataType: "text".
$.ajax({
type: "POST",
url: "111212.py",
data: { param: " "},
dataType: "text"
}).done(function( o ) {
alert("OK");
});
Second, fetching a local file from javascript may violate the Same Origin Policy, depending on the browser. See: Origin null is not allowed by Access-Control-Allow-Origin
An most important, fetching does not execute a file, it just reads it and returns as a string.
So apparently, as has been pointed out, this can't be done, not like this. So I'm going to start a simple CGI python sever to server the HTML file, and execute the script. I've tested it and it works great!

How to parse XML from another server using JavaScript or jQuery?

I am new to Javascript. I need to parse XML using javascript or jQuery which is another server. I tried by using the below code. But when I executed it, it was not going to success method.
I was able to parse the XML which is in the same folder. Is it possible in javascript to access content from another server. I read the Same Origin Policy.
I was able to get the success message, but cant get the xml data
$.ajax({
type: 'GET',
url: 'http://10.47.5.69/myxml.xml',
dataType: "xml",
success: function(data){
alert('success');
$(data).find("Node").each(function() {
alert($(this).find("element").text());
});
},
error: err
});
function err(xhr, reason, ex)
{
alert('xhr.status: ' + xhr.status);
alert('ex "'+ex);
}
You cannot load something from another server due to cross-domain security checks.
However for javascript, there is a workaround: the JSONP technique: http://en.wikipedia.org/wiki/JSONP
It is used for JSON data but it can just as well be used for any string data. But it will only work if you have some degree of control (i.e. can install a script) on that server.
Another alternative is to proxy that URL on your own server. That might be easier.

Categories

Resources