I'd like to know if HTML5 API may fit this use case:
some videos are present on a public server (say http://videosanbox.me/video.mpg)
the JS/html5 app should store the videos locally in order to be able to play them also off-line (videos are public, there are no security
warnings)
In my initial tests I am unable to go past the "No 'Access-Control-Allow-Origin'" error.
In my understanding the following script should:
request with a get the content located at the given URL
prepare 1Mb file somewhere (I assume I'll have other errors here, but I'll get there when I'll see them:))
for now I'm interested in understanding why this error is happening, wouldn't it be normal for a client (a mobile browser) to query for resources which are not already on it?
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://videosanbox.me/video.mpg', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
window.requestFileSystem(TEMPORARY, 1024 * 1024, function(fs) {
fs.root.getFile('video.mpg', {create: true}, function(fileEntry) {
fileEntry.createWriter(function(writer) {
writer.onwrite = function(e) { alert('writing'); };
writer.onerror = function(e) { alert('error'); };
var blob = new Blob([xhr.response], {type: 'video/mpg'});
writer.write(blob);
}, onError);
}, onError);
}, onError);
};
xhr.send();
onError is just doing something in case of error: function onError(e) {console.log('Error', e);}
Solution 1
On the server side, you need this header to be passed:
header('Access-Control-Allow-Origin: *');
Unfortunately, that may not be possible if you don't have control over videosanbox.me. If not, contact them and see if they're willing to allow this. If not, don't worry, there's a second solution:
Solution 2
Create a web page on your own server and allow cross site scripting (but use security to restrict who can use this page). In that page's code, it will take the request and open an HTTP connection to http://videosanbox.me, retrieve the mpg file and spit it back to the PhoneGap app as a Blob. Your PhoneGap would connect to this page (on your server) via Ajax instead of http://videosanbox.me.
Related
I have switch to http/2 and apache but upload progress does not work anymore.
I have track event.loaded in console and It reaches too fast 100% when the real upload is not finished, sometimes it's just started.
When i switch back to HTTP/1.1 all working fine with same function.
I have search all day about that problem and found some interesting post where other users report that anivirus was problem. On my pc i have Eset Internet Security and when i disable HTTPS scaning xhr progress is working normal. But also when i enable antivirus but disable http2 on site upload progress working fine. So only with http2 and antivirus enabled i have this problems.
There is any solution for this?
This is example and part of code which should back progress of upload.
function uploadFile_() {
var filedata = new FormData();
filedata.append("file1",file);
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", progressHandler, function(e) {
if (prevLoaded !== 0 && e.loaded <= prevLoaded) {
xhr.abort();
return;
}
prevLoaded = e.loaded;
},false);
xhr.addEventListener("load", completeHandler, false);
xhr.addEventListener("error", errorHandler, false);
xhr.addEventListener("abort", abortHandler, false);
xhr.open("POST", 'https://example.com/upload-api/video',true);
xhr.withCredentials = true;
xhr.send(filedata);
}
function progressHandler(event) {
var percent = (event.loaded / event.total)*100;
console.log(percent);
}
This is what i did
added a new loaction to handle upload
location = /upload {
proxy_pass http://localhost:80/upload.bin;
}
now with http2 post request the file is getting uploaded also working on http1.1
Answer by for my question by #Ferrybig
This is intentional.
NGINX knows that your renderer for a 405 error doesn't need any body, so with HTTP, it discards any received data. This is really how HTTP1.1 has been designed.
With HTTP2, it becomes smarter, it tells the other side to abort sending data, and sends the resulting page. This is done to prevent wasting internet packets for data that is going to be discarded anyway.
The way HTTP2 and higher works, is just smarter and wastes less of your data for things that are already known (for example, if you need to login for a file upload, it just tells the client as soon as possible that there is an error, instead waiting until your full file has been uploaded)
When you send a request to a .php file, the php process takes it over, and it doesn't have a way to instantly return a result, so NGINX streams the whole page to php before showing the error, because PHP only starts executing the code on the page once the file has been received, and it might do something with the POST request
I've been trying to get the top news story from Hacker News, though an example from any website would do.
Here is my code by the way:
let getHTML = function (url, callback) {
// Feature detection
if (!window.XMLHttpRequest) return;
// Create new request
let xhr = new XMLHttpRequest();
// Setup callback
xhr.onload = function () {
if (callback && typeof (callback) === 'function') {
callback(this.responseXML);
}
};
// Get the HTML
xhr.open('GET', url);
xhr.responseType = 'document';
xhr.send();
};
getHTML('https://news.ycombinator.com/news', function (response) {
let someElem = document.querySelector('#someElementFromMyPage');
let someOtherElem = response.querySelector('#someElementFromOtherPage');
someElem.innerHTML = someOtherElem.innerHTML;
});
This should display the element from other page and bring it to my page.
When I run your code, I get a CORS error in the browser dev-tools console (more details here).
Problem
Basically the target website (https://news.ycombinator.com/news) is restricting how a Browser can request it. And the browser conforms and respects this restriction.
The JS code makes the request.
The browser reads the response and looks at the HTTP headers included in the response from (https://news.ycombinator.com/news)
Because there's X-Frame-Options: DENY and X-XSS-Protection: 1 mode=block the browser won't let you read the request in the JS code, so you get an error.
Solution
There's many options for getting around CORS errors, you can research them yourself:
Funnel requests through a proxy-server, routing CORS requests through another server that strips off the pesky CORS headers. maybe this?
Run a server for web-scraping, servers don't have to respect Headers like the browser does, so you can GET anything. maybe try this
Scraping within the browser is increasingly hard, so you need to use other solutions to take content from other sites.
Hope this helps!
I'm trying to make an XML request inside the content.js file of a chrome extension I am making. I'm having trouble, however, making the request, and adding the appropriate event listeners. In the current configuration, the open after the listeners, the console says my request needs to be open before being sent, although you'll note that the send method is only called in the callback function when the request has been loaded. In the case that I put the open before the event listeners, the console says that the request has been aborted. If there is a better way of requesting and parsing XML data within a google chrome extension application, I would appreciate any advice. I've left the link in so you can see what type of XML data I'm dealing with.
var l = "https://video.google.com/timedtext?lang=en&v=5MgBikgcWnY";
function addScript () {
$(document).ready(function() {
$('#related').prepend('<div id="script-box" class="col s12"></div>');
$('#script-box').append('<h3 id="script-title">Quote</h3>');
var xhr = new XMLHttpRequest();
xhr.addEventListener("progress", console.log("The download is still in progress"));
xhr.addEventListener("abort", console.log("This process has been aborted"));
xhr.addEventListener("load", parseXML(xhr));
xhr.addEventListener("error", console.log("An error has ocurred."));
xhr.open('get', l, true);
});
}
function parseXML(r) {
r.send();
var result = r.responseText;
console.log(result);
}
I've been following this Google File Picker tutorial and I've gotten so far as to get the file picker showing and getting the URL, but I don't know how to download the file using JavaScript. If I can use VB.NET, then can someone point me in the right direction?
I've been able to download files with VB.NET from my own database, but I don't know how to get it with the Google API or with JavaScript.
All of the file picker code works, and I'm calling this from the onSelect of the FilePicker:
function downloadGDriveFile(file) {
if (file.downloadUrl) {
var accessToken = gapi.auth.getToken().access_token;
var xhr = new XMLHttpRequest();
xhr.open('GET', file.downloadUrl); // use selfLink??
xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
xhr.onload = function () {
var content = xhr.responseText;
};
xhr.onerror = function () {
alert('Download failure.');
};
xhr.send();
} else {
alert('Unable to download file.');
}
}
And when I click on the download URL I get this error:
"code": 403,
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
The error you posted is an issue with your account reaching it's max usage limit. Different issue than downloading the file. I don't have any knowledge on the google file picker api, but I'm going to assume this is in the browser.
You may have to specify req.responseType = "arraybuffer" because it could default to json.
I recommend using http://danml.com/download.html. Browser API does not expose the download modal for security reasons. The hack is to create an invisible a tag set the url to the blob of the body that you received and programmatically click the tag. The library provided does exactly that.
My goal is to read an HTTP MP3 audio stream from the browser and have access to the raw audio data.
HTML5 < audio > lets me easily play the stream, but, as far as I know, does not grant access to the raw audio data. It just plays it.
JS XMLHTTPRequest can download files through HTTP and process the raw audio data. It seems to be a good candidate, but it suffers from a limitation: it does not grant access to the binary data until the download is finished (readystate = 4). In my case, the stream is unlimited, so the readystate stays permanently at 3 and the XHR response is null (this behavior is detailed in the mozilla documentation). Note that the cross-origin policy of the server I am connecting to is Access-Control-Allow-Origin: *
Code sample that works for local regular files, but not for streams. I get a null pointer exception at request.response.length
request = new XMLHttpRequest();
//request.open('GET', 'test.mp3', true);
request.open('GET', 'http://domain.com/stream.mp3', true);
request.responseType = 'arraybuffer';
request.onload = function() {
console.log("request onload");
var audioData = request.response;
audioCtx.decodeAudioData(audioData,
function(buffer) { myBuffer = buffer; source.buffer = myBuffer; },
function(e){"Error with decoding audio data" + e.err}
);
}
request.onreadystatechange = function() {
console.log("ready state = " + request.readyState);
console.log(request.response.length);
}
request.send();
Does anybody know alternatives or workarounds to those options, so that the raw binary packets can be read while downloading the stream?
Note that I don't have control on the server. It's an icecast http stream.
Also, on the browser side, I'd like to avoid using Flash.
Thank you
Edit: to clarify possible cross-origin questions, the JS is run on a page hosted in a localhost server.
The following workaround worked:
As stated in MDN https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data, it is possible to override the MIME type of http request, setting it to custom, and call responseText.
function load_binary_resource(url) {
var req = new XMLHttpRequest();
req.open('GET', url, false);
//XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
req.overrideMimeType('text\/plain; charset=x-user-defined');
req.send(null);
if (req.status != 200) return '';
return req.responseText;
}
The point is that req.responseText does not suffer from the same limitation of req.response. It is not null in the state readystate=3.
Then, the binary responseText is accessed with
var filestream = load_binary_resource(url);
var abyte = filestream.charCodeAt(x) & 0xff; // throw away high-order byte (f7)
A significant drawback is that req.responseText keeps growing as the stream is downloaded. The request should be reset from time to time to avoid excessive RAM consumption.