I want to show a pdf file from a GET request on a HTML page using plain Java Script.
The api returns a pdf-file.
This is the postman response of the api:
Here is my code so far:
function getImg() {
var url = "https://api.herokuapp.com/download"
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.setRequestHeader("Authorization", "JWT " + localStorage.getItem('token'));
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.send(null);
xhr.addEventListener('load', function() {
var responseObject = this.response;
var myImage = new Image();
myImage = this.response;
document.body.appendChild(myImage);
});
}
I get this error:
TypeError: Argument 1 of Node.appendChild is not an object.
How can this be done?
Any help is very appreciated.
BR KRESTEN
Here is how I solve this:
function getImg() {
var url = "https://secure.gravatar.com/avatar/3167fa1b890ffe735393de7d6296e32d?s=58&d=mm&r=g"
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
// xhr.setRequestHeader("Authorization", "JWT " + localStorage.getItem('token'));
// xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.send(null);
xhr.addEventListener('load', function() {
if (this.status === 200) {
let blob = this.response;
let myImage = new Image();
myImage.src = window.URL.createObjectURL(blob);
document.body.appendChild(myImage);
}
});
}
I am sending a XMLHttpRequest to a MVC Controller and i am expecting to receive a file as a result.
When debugging with the browser i am getting a response that is ok , but i do not know why it is not as a file:
JS
window.submit=function () {
return new Promise((resolve, reject) => {
var form = document.getElementById("newTestForm");
var data = new FormData(form);
var xhr = new XMLHttpRequest();
var method = form.getAttribute('method');
var action = form.getAttribute('action');
xhr.open(method, action);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(xhr.response); //response looks ok...but no file starts downloading
}
else if (xhr.status != 200) {
reject("Failed to submit form with status" + xhr.status);
}
}
xhr.send(data);
});
}
Controller
[HttpPost]
[Route([Some Route])]
public async Task BenchAsync(object request)
{
try
{
string fileName = "results.txt";
object result = await service.RunAsync(request);
byte[] data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(result));
this.Response.ContentType = "application/octet-stream";
this.Response.ContentLength = data.Length;
using(MemoryStream stream=new MemoryStream(data))
{
await stream.CopyToAsync(this.Response.Body);
}
}
catch (Exception ex)
{
throw;
}
}
I have solved it thanks to this Post
It seems i had to transform the response into a BLOB , create a download link and point it towards this blob and the created link in order to download the file.
So the function looks like :
window.submit= function () {
return new Promise((resolve, reject) => {
var form = document.getElementById("newTestForm");
var data = new FormData(form);
var xhr = new XMLHttpRequest();
var method = form.getAttribute('method');
var action = form.getAttribute('action');
xhr.open(method, action);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
var blob = new Blob([this.response], { type: 'image/pdf' });
let a = document.createElement("a");
a.style = "display: none";
document.body.appendChild(a);
let url = window.URL.createObjectURL(blob);
a.href = url;
a.download = 'mytext.txt';
a.click();
window.URL.revokeObjectURL(url);
}
else if (xhr.status != 200) {
reject("Failed to submit form with status" + xhr.status);
}
}
xhr.send(data);
});
}
P.S i do not know what the type of the blob is named for txt but it works as well , given the right extension.
I observed a very strange behavior. If I set a button from web to upload string to S3, it works fine. But if I set a button from web to bring up a bootstrap modal, then from this modal I set a button to upload the string, it doesn't work.
Frontend is like below in both cases. The difference is whether clicking to run function 'saveToAWS' from web or from modal as 2-step-process, the latter returns xhr.status as 0.
function saveToAWS() {
var file = new File([jsonStr], "file.json", { type: "application/json" });
var xhr = new XMLHttpRequest();
var fn=file.name;
var ft = file.type;
xhr.open("GET", "/sign_s3_save?file-name=" + fn + "&file-type=" + ft);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
console.log('signiture returned')
save_file(file, response.signed_request, response.url);
}
else {
alert("Could not get signed URL.");
}
}
};
xhr.send();
}
function save_file(file, signed_request, url) {
var xhr = new XMLHttpRequest();
xhr.open('PUT', signed_request);
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log('200');
}
else {
alert('cannot upload file');
}
}
};
xhr.send(file);
}
Backend as Node.js, in order to get a signed URL:
app.get('/sign_s3_save', isLoggedIn, function (req, res) {
var fileName = req.query['file-name'];
var fileType = req.query['file-type'];
aws.config.update({ accessKeyId: AWS_ACCESS_KEY, secretAccessKey: AWS_SECRET_KEY });
var s3 = new aws.S3();
var ac = req.user._id;
var timenow = Date.now().toString();
var fileRename = ac + '/json/' + timenow + '.json';
var s3_params = {
Bucket: S3_BUCKET,
Key: fileRename,
Expires: 60,
ContentType: fileType,
ACL: 'public-read'
};
s3.getSignedUrl('putObject', s3_params, function (err, data) {
if (err) {
console.log(err);
}
else {
var return_data = {
signed_request: data,
url: 'https://' + S3_BUCKET + '.s3.amazonaws.com/' + fileRename
};
res.write(JSON.stringify(return_data));
res.end();
}
});
});
Any suggestion, please?
I am using rtcmulticonnection.js. I want to save the video on server. Here are two files "index.html" and "save.php".
request.open("POST", url); does not post the data
here the source file link
"https://github.com/muaz-khan/RTCMultiConnection/blob/master/v2.2.2/demos/audio-video-screen-sharing-recording.html"
index.html
document.getElementById('recordAudioVideo').onclick = function() {
var localVideoStream = rmc.streams.selectFirst({
video: true,
local: true
});
if (!localVideoStream) return;
var recordingSession = {
audio: true,
video: true
};
var button = this;
if (button.innerHTML == 'Record Audio/Video') {
button.innerHTML = 'Stop Recording Audio/Video';
// http://www.rtcmulticonnection.org/docs/startRecording/
localVideoStream.startRecording(recordingSession);
} else if (button.innerHTML == 'Stop Recording Audio/Video') {
// http://www.rtcmulticonnection.org/docs/stopRecording/
localVideoStream.stopRecording(function(blob) {
//alert('Audio blob size in bytes: ' + blob.audio.size);
//alert('Video blob size in bytes: ' + blob.video.size);
var fileType = 'video'; // or "audio"
var fileName = 'ABCDEF.webm'; // or "wav"
var formData = new FormData();
formData.append(fileType + '-filename', fileName);
formData.append(fileType + '-blob', blob);
console.log(formData);
xhr('save.php', formData, function (fName) {
window.open(location.href + fName);
});
function xhr(url, data, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (request.readyState == 4 && request.status == 200) {
callback(location.href + request.responseText);
}
};
request.open("POST", url);
request.send(data);
}
button.innerHTML = 'Record Audio/Video';
}, recordingSession);
}
save.php
<?php
// Muaz Khan - www.MuazKhan.com
// MIT License - https://www.webrtc-experiment.com/licence/
// Documentation - https://github.com/muaz-khan/WebRTC-Experiment/tree/master/RecordRTC
foreach(array('video', 'audio') as $type) {
if (isset($_FILES["${type}-blob"])) {
echo 'uploads/';
$fileName = $_POST["${type}-filename"];
$uploadDirectory = './'.$fileName;
if (!move_uploaded_file($_FILES["${type}-blob"]["tmp_name"], $uploadDirectory)) {
echo(" problem moving uploaded file");
}
echo($fileName);
}
}
?>
the problem is at
request.open("POST", url);
request.send(data);
request.open("POST", url); does not post the data.it does not call url(means save.php).because i have alert some text to see if save.php is called or not. so it does not show any alertbox on client.how can i solve this problem.Also it shows no error on posting.
I am trying to play with tvOS, and I have small question regarding handling json call. I have to get some data through an API, let's say for sake of test that I am calling this link
http://query.yahooapis.com/v1/public/yql?q=select%20item%20from%20weather.forecast%20where%20location%3D%223015%22&format=json
I tried to use this function with some modification
function getDocument(url) {
var templateXHR = new XMLHttpRequest();
templateXHR.responseType = "json";
templateXHR.open("GET", url, true);
templateXHR.send();
return templateXHR;
}
but didn't work out. Any hints or help ?
If I need to use NodeJS, how can I do that ?
This is one that I got working. It's not ideal in many respects, but shows you something to get started with.
function jsonRequest(options) {
var url = options.url;
var method = options.method || 'GET';
var headers = options.headers || {} ;
var body = options.body || '';
var callback = options.callback || function(err, data) {
console.error("options.callback was missing for this request");
};
if (!url) {
throw 'loadURL requires a url argument';
}
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.onreadystatechange = function() {
try {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
callback(null, JSON.parse(xhr.responseText));
} else {
callback(new Error("Error [" + xhr.status + "] making http request: " + url));
}
}
} catch (err) {
console.error('Aborting request ' + url + '. Error: ' + err);
xhr.abort();
callback(new Error("Error making request to: " + url + " error: " + err));
}
};
xhr.open(method, url, true);
Object.keys(headers).forEach(function(key) {
xhr.setRequestHeader(key, headers[key]);
});
xhr.send();
return xhr;
}
And you can call it with the following example:
jsonRequest({
url: 'https://api.github.com/users/staxmanade/repos',
callback: function(err, data) {
console.log(JSON.stringify(data[0], null, ' '));
}
});
Hope this helps.
I tested this one out on the tvOS - works like a charm with jQuery's syntax (basic tests pass):
var $ = {};
$.ajax = function(options) {
var url = options.url;
var type = options.type || 'GET';
var headers = options.headers || {} ;
var body = options.data || null;
var timeout = options.timeout || null;
var success = options.success || function(err, data) {
console.log("options.success was missing for this request");
};
var contentType = options.contentType || 'application/json';
var error = options.error || function(err, data) {
console.log("options.error was missing for this request");
};
if (!url) {
throw 'loadURL requires a url argument';
}
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = timeout;
xhr.onreadystatechange = function() {
try {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
if (xhr.responseType === 'json') {
success(null, xhr.response);
} else {
success(null, JSON.parse(xhr.responseText));
}
} else {
success(new Error("Error [" + xhr.status + "] making http request: " + url));
}
}
} catch (err) {
console.error('Aborting request ' + url + '. Error: ' + err);
xhr.abort();
error(new Error("Error making request to: " + url + " error: " + err));
}
};
xhr.open(type, url, true);
xhr.setRequestHeader("Content-Type", contentType);
xhr.setRequestHeader("Accept", 'application/json, text/javascript, */*');
Object.keys(headers).forEach(function(key) {
xhr.setRequestHeader(key, headers[key]);
});
if(!body) {
xhr.send();
} else {
xhr.send(body);
}
return xhr;
}
Example queries working on Apple TV:
var testPut = function(){
$.ajax({
type: 'PUT',
url: url,
success: successFunc,
error: errFunc,
dataType: 'json',
contentType: 'application/json',
data: data2
});
}
var testGet = function(){
$.ajax({
dataType: 'json',
url: url,
success: successFunc,
error: errFunc,
timeout: 2000
});
}
var getLarge = function(){
$.ajax({
dataType: 'json',
url: url,
success: successFunc,
error: errFunc,
timeout: 2000
});
}
Did you call your function in the 'App.onLaunch'
App.onLaunch = function(options) {
var url = 'http://query.yahooapis.com/v1/public/yql?q=select%20item%20from%20weather.forecast%20where%20location%3D%223015%22&format=json';
var doc = getDocument(url);
console.log(doc);
}
Might be worth looking at https://mathiasbynens.be/notes/xhr-responsetype-json
I came across this question looking to accomplish the same thing, and was inspired by #JasonJerrett's answer, but found it a bit lacking because in my instance I am using an XML template built in Javascript like this:
// Index.xml.js
var Template = function() {
return `very long xml string`;
};
The issue is that you can't perform the XHR request inside the template itself, because the template string will be returned back before the XHR request actually completes (there's no way to return data from inside an asynchronous callback). My solution was to modify the resource loader and perform the XHR request there, prior to calling the template and passing the data into the template function:
ResourceLoader.prototype.loadResource = function(resource, dataEndpoint, callback) {
var self = this;
evaluateScripts([resource], function(success) {
if (success) {
// Here's the magic. Perform the API call and once it's complete,
// call template constructor and pass in API data
self.getJSON(dataEndpoint, function(data) {
var resource = Template.call(self, data);
callback.call(self, resource);
});
} else {
var title = "Failed to load resources",
description = `There was an error attempting to load the resource. \n\n Please try again later.`,
alert = createAlert(title, description);
Presenter.removeLoadingIndicator();
navigationDocument.presentModal(alert);
}
});
}
// From: https://mathiasbynens.be/notes/xhr-responsetype-json
ResourceLoader.prototype.getJSON = function(url, successHandler, errorHandler) {
var xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.onreadystatechange = function() {
var status;
var data;
if (xhr.readyState == 4) {
status = xhr.status;
if (status == 200) {
data = JSON.parse(xhr.responseText);
successHandler && successHandler(data);
} else {
errorHandler && errorHandler(status);
}
}
};
xhr.send();
};
Then the template function needs to be modified to accept the incoming API data as a parameter:
// Index.xml.js
var Template = function(data) {
return 'really long xml string with injected ${data}';
};
You need to implement the onreadystatechange event on the XHR object to handle the response:
templateXHR.onreadystatechange = function() {
var status;
var data;
if (templateXHR.readyState == 4) { //request finished and response is ready
status = templateXHR.status;
if (status == 200) {
data = JSON.parse(templateXHR.responseText);
// pass the data to a handler
} else {
// handle the error
}
}
};
If you want to call the request on app launch, just add in application.js:
App.onLaunch = function(options) {
var javascriptFiles = [
`${options.BASEURL}js/resourceLoader.js`,
`${options.BASEURL}js/presenter.js`
];
evaluateScripts(javascriptFiles, function(success) {
if(success) {
resourceLoader = new ResourceLoader(options.BASEURL);
var index = resourceLoader.loadResource(`${options.BASEURL}templates/weatherTemplate.xml.js`, function(resource) {
var doc = Presenter.makeDocument(resource);
doc.addEventListener("select", Presenter.load.bind(Presenter));
doc.addEventListener('load', Presenter.request);
navigationDocument.pushDocument(doc);
});
} else {
var errorDoc = createAlert("Evaluate Scripts Error", "Error attempting to evaluate external JavaScript files.");
navigationDocument.presentModal(errorDoc);
}
});
}
In presenter.js add a method:
request: function() {
var xmlhttp = new XMLHttpRequest() , method = 'GET' , url = 'your Api url';
xmlhttp.open( method , url , true );
xmlhttp.onreadystatechange = function () {
var status;
var data;
if (xmlhttp.readyState == 4) {
status = xmlhttp.status;
if (status == 200) {
data = JSON.parse(xmlhttp.responseText);
console.log(data);
} else {
var errorDoc = createAlert("Evaluate Scripts Error", "Error attempting to evaluate external JavaScript files.");
navigationDocument.presentModal(errorDoc);
}
}
};
xmlhttp.send();
},