Javascript delete blobs from xmlhttprequest - javascript

I have a web app that pre-loads videos by requesting blobs and creating blob urls.
// Get video Blob URL
const url = 'https://www.some-video-url.com/video.mp4';
const xhr = new XMLHttpRequest();
xhr.open('GET', sourceUrl, true);
xhr.responseType = 'blob';
xhr.onprogress = () => {console.log('downloading')};
const blobUrl;
xhr.onload = () => {
blobUrl = URL.createObjectURL(req.response);
console.log('done');
};
xhr.send();
...
// After using video
URL.revokeObjectURL(blobUrl);
I would send such requests multiple times. It work fine in the beginning, however, when I send too many of these requests I get this error.
VM1853:10 GET https://www.some-video-url.com/video.mp4 net::ERR_FAILED 200
I am running this on Chrome and it here is my hypothesis.
According to this documentation it seems like Blob storage limit for chrome is 10% of total disk space. I confirmed this by sending xhr request to GET a 2 GB file until I hit the error. It got an error when I sent request for 20 of the 2GB files. It seems like the blobs are not garbage collected because it is not properly de-referenced. This mysterious reference seems to be related to the xhr.
In my application, I would like to
1. Start downloading videos in the background
2. Client watches a video
3. When the video playback is done, remove the video
Is there a reliable way to execute step 3? I would like the Blob to be deleted after its use.

Related

MediaSource fetching/downloading

When I try to fetch MediaSource object via blob link or send GET XMLHttpRequest I'm getting the error net::ERR_FILE_NOT_FOUND.
This happened for youtube or instagram MediaSource links.
eg
var xhr = new XMLHttpRequest;
xhr.open('get', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
some_Further_CallBack(xhr.response);
};
xhr.send();
I'm completelly stuck, please say me what I'm doing wrong.
The blob: URL when created from a MediaSource can not be fetched from that URL. Note that even when it's created from a Blob, it's not the same Blob object that you fetch.
The best is to keep your MediaSource instance available in a variable, but in cases you can't (e.g because you're not the author of the page), you can add some hooks on the URL methods to save the original object and retrieve it later as exposed in this answer of mine. But note that you'd need this script to be ran BEFORE the page's use of URL.creatObjectURL(), which means that in your case you will probably need an user-script to inject it as soon as possible.
Try get error after send
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/error_event
But i think is not possible get content from youtube by XMLHttpRequest

XHR Upload Progress, HTTP/2 and antivirus

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

Rename or Download File from Firebase Storage in JavaScript

Is there any way to rename or download the file from the firebase storage?
I don't see the rename method nor download method.
I tried to download the file by the url and it doesn't work at all
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", "downloadURL");
xhr.responseType = "blob";
xhr.onload = function()
{
blob = xhr.response;//xhr.response is now a blob object
console.log(blob);
}
xhr.send();
It returns
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Two things here:
1) you want to use the getDownloadURL() method (docs) to get a public download URL, that way you can simply drop your item in an <img> tag, allow users to click on it to download it, or use an XMLHttpRequest to get the bytes.
2) you'll want to enable CORS on your objects, see: Firebase Storage and Access-Control-Allow-Origin
Trigger click with javascript...
download filename.txt

XMLHttpRequest and http streaming

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.

File API - HTML5 App to store videos

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.

Categories