I've this WebAPI method, that takes a custom object MyType as input and generate a PDF based on that. The PDF-file is returned as a HttpResponseMessage. Note that I specify the filename on response.Content.Headers.ContentDisposition.FileName:
ASP.NET WebAPI
[Route("")]
public HttpResponseMessage Get([FromUri]MyType input)
{
var pdfContent = PdfGenerator.Generate(input);
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = pdfContent;
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = "MyCustomFileName.pdf"
return response;
}
In AngularJS I fetch the file using FileSaver.js like this:
$http.get("api/pdf/", {
params: {
"type": myObject
},
responseType: 'arraybuffer'
}).then(function (results) {
var data = results.data;
var file = new Blob([data], { type: 'application/pdf' });
saveAs(file, 'filename.pdf');
}, function (results) {
console.log(results);
});
It works as excepted, but I'm defining the filename both on WebAPI and in the JavaScript. Is there a way, that I can retrieve the FileName defined in WebAPI in the results variable in JavaScript?
The promise returned by methods of $http are passed as argument an object with the following properties (ref):
data – {string|Object} – The response body transformed with the transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
So results.headers('Content-Disposition') will gives you the value of the Content-Disposition header. You will have to do some trivial parsing to get to the actual filename.
Related
How can I do a http get request and pass an json Object
This is my json-Object
{{firstname:"Peter", lastname:"Test"}
and this Object I want to pass in the http request to get a list Of matched persons.
how is it possible? This example just shows a simple get request with a json result. How do I have to modify it?
//Component:
person:Person;
persons:Person [];
....
//Whre can I pass the person, here in the service??
getMatchedPersons(){
this.httpService.getMatchedPersons().subscribe(
data => this.persons = data,
error => aller(error)
);
);
//SERVICE
//pass parameters?? how to send the person object here?
getMatchedPersons(){
return this.http.get('url').map(res => res.json());
}
The Http.get method takes an object that implements RequestOptionsArgs as a second parameter.
The search field of that object can be used to set a string or a URLSearchParams object.
An example:
// Parameters obj-
let params: URLSearchParams = new URLSearchParams();
params.set('firstname', yourFirstNameData);
params.set('lastname', yourLastNameData);
//Http request-
return this.http.get('url', {
search: params
}).subscribe(
(response) => //some manipulation with response
);
For pure javascript:
You must serialize your json to a list of parameters:
?firstname=peter&lastname=test
and append it to the URL because GET requests have no body.
There are a few ways of converting JSON to QueryParameters.
They are addressed in this question: Is there any native function to convert json to url parameters?
There you can choose the poison of your liking, mine was:
function obj_to_query(obj) {
var parts = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
}
}
return "?" + parts.join('&');
}
But mind you that GET requests must obbey the URL limit that based on this answer is recomended to stay under 2000 characters to be safe:
RFC says 8000
IE8 and IE9 go as far as 2083
Search engines only read to 2048
Using Angular2 URLSearchParams
With the same method of converting a plain JSON to arguments one could use URLSearchParams as suggested by Рома Скидан:
let params: URLSearchParams = objToSearchParams(obj);
return this.http.get('url', {
search: params
}).subscribe(
(response) => //some manipulation with response
);
function objToSearchParams(obj): URLSearchParams{
let params: URLSearchParams = new URLSearchParams();
for (var key in obj) {
if (obj.hasOwnProperty(key))
params.set(key, obj[key]);
}
return params;
}
Maybe you want to stringify the json object
var json = JSON.stringify(myObj);
this.http.get('url'+'?myobj='+encodeURIComponent(json))
Use a POST request to pass objects to the server:
//SERVICE
getMatchedPersons(searchObj: any){
return this.http.post('url', JSON.stringify(searchObj))
.map(res => res.json());
}
Then you can pass whatever JS object you want and send it to the server in your http request.
getMatchedPersons(searchObj: any){
this.httpService.getMatchedPersons(searchObj: any).subscribe(
data => this.persons = data,
error => alert(error);
);
);
Similar to AngJobs' but maybe more up-to-date?? Calling encodeURIComponent is not necessary. Here's the Angular:
const stringifiedParams = JSON.stringify(this.filterParams);
return this.http.get<any[]>(`persons`, {params: {filter: stringifiedParams}});
On the server Node deserializes the params with JSON.parse:
filter = JSON.parse(req.query.filter.toString());
Actually there's an easier way for flushing parameters
getMatchedPersons(myObject: any): Observable<Person[]> {
return this.http.get<Person[]>('url', { params: { ...myObject } });
}
The above code represents a function that accepts a JSON object myObject as a parameter.
HttpClient.get method accepts an options paramter as its second paramter.
The options parameter contains many useful keys, but we're only interested with the params key in our case.
the value of params is { ...myObject }, that is- we're using the spread operator to pass all key:value pairs from an object.
Refer that this will do the job, and will not make the URL look ugly with all those ? and key=value and & characters, of course in either case those parameters won't be shown for the user since it's just an HTTP call, but still, if anyone is using a logger interceptor, they will have a clean log.
I am new to Node.js and I have created a method that should asynchronously fetch jsonp data via ajax and display the retrieved content in a graph. This method works fine when the url points to a static js file (in this case productsData.js) containing jsonp data:
function loadChart(destElementId, alertId) {
$.ajax({
url:'http://localhost:3000/products/data/productsData.js',
type: "GET",
data: {prodId: prodId},
jsonp: true,
dataType : 'json',
jsonpCallback: "jsonpCallback"
});
window["jsonpCallback"] = function(data) {
populateData(data, destId);
}
}
As in normal applications, I want to pass real data fetched via an external web service. I have created the following js file (data-client.js) that retrieves data from a specific web service. When calls are browser-based, the data is fetched successfully as a normal json and is displayed accordingly in the browser.
var express = require('express');
var router = express.Router();
var http = require('http');
var yaml_config = require('node-yaml-config');
var config = yaml_config.load(__dirname + '/../config/app-config.yml');
router.get('/data/:id', function (req, res, next) {
var opts = {
host: config.alertService.host,
port: config.alertService.port,
method: 'GET',
path: '/DataService/rest/receiveData/' + req.params.id
}
var reqGet = http.request(opts, function (dataResponse) {
var responseString = '';
dataResponse.on('data', function (data) {
responseString += data;
});
var response = {x:[],y:[],z:[],t:[]};
dataResponse.on('end', function () {
var responseObject = JSON.parse(responseString);
var accs = responseObject.data.listPCS;
for(var i in accs){
response.x.push(accs[i].accX);
response.z.push(accs[i].accY);
response.y.push(accs[i].accZ);
response.t.push(accs[i].timestamp);
}
res.json(response);
});
});
reqGet.end();
reqGet.on('error', function (e) {
console.error(e);
});
});
module.exports = router;
The first step for using live jsonp data is to replace the previous url value with:
url: 'http://localhost:3000/products/data/'+productId,
The second step is to replace in the data-client.js:
res.json(response);
with:
res.jsonp('jsonpCallback('+ JSON.stringify(response) + ');');
Somehow the data is not fetched. When I try to get the data via the browser (i.e. by entering http://localhost:3000/data/ID937) however I get the following result:
"jsonpCallback({\"x\":[1,1,1],\"y\":[2,1,4],\"z\":[0,0,9],\"t\":[1462790772000,1462790772010,1462790772020]});"
Can someone please tell me where the problem may be? I would be very thankful.
It looks like you are using Express.
jsonp() expects to be passed your raw data, not a string containing the complete response. It also expects to read the callback name from the query string, which jQuery will generate for you if you let it.
So the first thing to do is to fix your client side code so it passes the callback name correctly
On the client
$.ajax({
url: 'http://localhost:3000/products/data/' + productId,
dataType: 'jsonp',
}).done(function(data) {
populateData(data, destId);
});
The changes here are:
GET is the default (and, for JSONP, only option) so there is no need to specify the type.
You are passing the data as a URL path part, not a query string. Drop the data property that you aren't using.
The jsonp property is used to override the callback name. That's harmful, don't do that (likewise, don't specify jsonpCallback). jQuery will generate one for you and add it to the query string.
If you are dealing in JSONP then specify that as the data type, not JSON.
Don't create your own global manually. Pass your function to done and let jQuery make it a global (with a generated name to match the callback).
On the server
Just pass the data structure you want to send back to jsonp().
res.jsonp(response);
The callback name will be read from the query string by Express.
Snapped code returns data from url in JSON format, how to create function to read data returned by this code in JQuery ?
var RealDataApi = function () {
var url_getgatedata = "api/realdata/getgatedata";
return {
getGateData: function (done, fail, always) {
var jqxhr = $.get(url_getgatedata);
jqXhrHandler(jqxhr, done, fail, always);
},
You can take the headers or parameters in the URL and by using postman you can get the JSON.
Some of the headers will be encrypted in the URL.
Following github API's documentation for pagination, I'm trying to request event items and retrieve the Link header (just like they suggest) to build the pagination. The problem is that I don't know how to handle the headers('Link') object.
Function:
getEvents: function(page) {
if(cacheService.get('eventos_'+page)) {
return cacheService.get('eventos_'+page);
} else {
var deferred = $q.defer();
$http.get('https://api.github.com/repos/'+owner+'/'+repo+'/events', {params: {per_page: 15, page: page}})
.success(function(events, status, headers) {
console.log(events, status, headers('Link'));
cacheService.put('eventos_'+page, events);
deferred.resolve(events);
}).error(function(err) {
deferred.reject('Error', err);
});
return deferred.promise;
}
}
The resulting "object" (if it can be called like that) is:
"
<https://api.github.com/repositories/XXXXXX/events?page=2&per_page=15>; rel="next",
<https://api.github.com/repositories/XXXXXX/events?page=4&per_page=15>; rel="last"
"
¿How can save page (next and last) numbers in $scope variables? or at least how can I traverse that object?
Don't laugh, but I tried headers('Link').rel['last'] without success, of course.
From the angular $http document https://docs.angularjs.org/api/ng/service/$http
The response object has these properties:
data – {string|Object} – The response body transformed with the transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
And to get data from headers its headers['Link'] if you can see 'Link' in your response header
Below is the code to get pagination links from header if you are sending pagination parameters in response header
function parseHeader(header){
// Split parts by comma
var parts = header.split(',');
var links = {};
// Parse each part into a named link
angular.forEach(parts, function (p) {
var section = p.split(';');
if (section.length != 2) {
throw new Error("section could not be split on ';'");
}
var url = section[0].replace(/<(.*)>/, '$1').trim();
var queryString = {};
url.replace(
new RegExp("([^?=&]+)(=([^&]*))?", "g"),
function($0, $1, $2, $3) { queryString[$1] = $3; }
);
var page = queryString['page'];
if( angular.isString(page) ) {
page = parseInt(page);
}
var name = section[1].replace(/rel="(.*)"/, '$1').trim();
links[name] = page;
});
return links;
}
This is my front-end code (using fetch)
var MyModel = Backbone.Model.extend();
var MyCollection = Backbone.Collection.extend({
url: '/questions',
model: MyModel
});
var coll = new MyCollection();
coll.fetch({
error: function (collection, response) {
console.log('error', response);
},
success: function (collection, response) {
console.log('success', response);
}
});
and this is my back-end code (using app.get)
app.get('/questions', function (request, response) {
console.log('Inside /questions');
response.writeHead(200, {
'Content-Type': 'text/json'
});
response.write('{test:1}');
response.end();
});
The problem is that although the response is as expected, the client-side error callback is called. When I remove the line response.write('{test:1}');, the success callback is called. Any ideas as to what I might be doing wrong?
Well {test:1} is not valid JSON.
{ "test":"1" }
OR
{ "test":1 }
is however, try one of those instead.
Keys are strings in JSON, and strings in JSON must be wrapped in double quotes check out JSON.org for more information.
To ensure you have valid JSON for more complex objects just use JSON.stringify():
var obj = { test : 1 };
response.write(JSON.stringify(obj)); //returns "{"test":1}"
Also, the correct Content-Type for json is application/json
{test:1} isn't valid JSON, you should try { "test":"1" }.
Another solution is to check Express's render.json function to see how it does sending json to the browser:
https://github.com/visionmedia/express/blob/master/lib/response.js#L152-172
If you're using express you need to res.send will automatically convert objects into JSON. If you're worried about it, there's a new one called res.json that will convert anything into JSON.
var obj = {super: "man"}
res.send(obj) // converts to json
res.json(obj) // also converts to json
You don't need need writeHead(), write(), or end().
http://expressjs.com/guide.html