Why can't my filereader read this data url from a xmlhttprequest - javascript

let MY_URL = "*"
let DataURL;
// basic JS way of getting the info from S3
let request = new XMLHttpRequest();
request.open('GET', MY_URL, true);
request.responseType = 'blob';
request.onload = function() {
var reader = new FileReader();
reader.readAsDataURL(request.response);
reader.onload = function(e){
DataURL = e.target.result;
};
};
request.send();
listenGetImageLoad(DataURL);
Here I am getting the Data URL of a file I am getting from the web. Next I want to Read it into a fileReader, but I keep getting the bug:
Uncaught TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'.
My code for the fileReader is as follows::
const listenGetImageLoad = (DataURL) => {
const imageArray = Object.keys(images)
let async = imageArray.length
for (let image in images) {
const reader = new FileReader()
reader.addEventListener("load", () => {
const imageObject = new Image()
imageObject.addEventListener("load", (event) => {...})
reader.readAsDataURL(DataURL)
}
}
This function seems to be failing at reader.readAsDataURL(DataURL). I have no idea as to why this is the case. I am so sure that I have inputted a data URL into the FileReader function too.

You have two problems
You are calling listenGetImageLoad at the wrong time. XMLHttpRequest is async. So you need to call that inside your onload event.
Even when you correct the async issue you are passing the wrong thing to readAsDataURL(). It expects a blob or file object to be passed to it, not a string which is what a data url is.
Call listenGetImageLoad inside the load event passing in the response from the request to fix your issue.
request.onload = function() {
listenGetImageLoad(request.response);
};
Note you do not need to use readAsDataURL to show an image from a blob. Just call URL.createObjectURL() passing in the blob/file to get a url the browser will be able to load. Then set the src of the image with that url.
request.onload = function() {
var url = URL.createObjectURL(request.response);
yourImage.src = url;
};

Related

How to use UTF-8 image data (png/jpeg/gif) from ajax call to render image to user?

I am using Bing Maps where you can use a POST call to get image data (png/jpeg/gif).
https://learn.microsoft.com/en-us/bingmaps/rest-services/imagery/get-a-static-map
Neither can I render the image to the user nor is it possible to download the file and display it when opened locally (the download works but the image file won't show an image).
This is the code that handles the image data from the POST request to the bing maps api:
// rsp contains UTF-8 image data (png)
let reader = new FileReader();
let file = new File([rsp], 'test.png');
// trying to render to user
reader.onloadend = function () {
document.getElementById('img').src = 'data:image/png;base64,' + reader.result.substr(37); // substr(37) will get base 64 string in a quick and dirty way
};
reader.readAsDataURL(file);
// trying to make the image downloadable (just for testing purposes)
var a = document.createElement("a"),
url = URL.createObjectURL(file);
a.href = url;
a.text = "Test";
a.download = 'test.png';
document.body.appendChild(a);
The solution was to use a native XMLHttpRequest with responseType 'blob' or 'arraybuffer' to handle the binary server response (https://stackoverflow.com/a/33903375/6751513).
var request = new XMLHttpRequest();
request.open("POST", bingMapsPOSTEndpoint + '&' + queryParamsString, true);
request.responseType = "blob";
request.onload = function (e) {
var dataURL = URL.createObjectURL(request.response);
document.getElementById('img').src = dataURL;
};
request.send();

How correctly store .js files to Localstorage of a browser

Can you please tell me how can I correctly store some js file to localstorage and then run it.
So I have found some code that stores an image, but can I store a js file?
Here is the code:
https://gist.github.com/robnyman/1875344
// Getting a file through XMLHttpRequest as an arraybuffer and creating a Blob
var rhinoStorage = localStorage.getItem("rhino"),
rhino = document.getElementById("rhino");
if (rhinoStorage) {
// Reuse existing Data URL from localStorage
rhino.setAttribute("src", rhinoStorage);
}
else {
// Create XHR and FileReader objects
var xhr = new XMLHttpRequest(),
fileReader = new FileReader();
xhr.open("GET", "rhino.png", true);
// Set the responseType to blob
xhr.responseType = "blob";
xhr.addEventListener("load", function () {
if (xhr.status === 200) {
// onload needed since Google Chrome doesn't support addEventListener for FileReader
fileReader.onload = function (evt) {
// Read out file contents as a Data URL
var result = evt.target.result;
// Set image src to Data URL
rhino.setAttribute("src", result);
// Store Data URL in localStorage
try {
localStorage.setItem("rhino", result);
}
catch (e) {
console.log("Storage failed: " + e);
}
};
// Load blob as Data URL
fileReader.readAsDataURL(xhr.response);
}
}, false);
// Send XHR
xhr.send();
}

How to upload any file using MS Graph API?

I am following this and I want to upload any type of file to OneDrive. It says that it accepts a buffer for the file content but my following code does not seem to work in case of any type of file. The file gets uploaded but it cannot be opened so the contents are messed up for sure.
Using the following method I am trying to get the body contents so that I can send them with the request.
private fileToBuffer(file: File): Observable<any> {
return Observable.create(observer => {
var arrayBuffer;
var fileReader = new FileReader();
fileReader.onload = function () {
arrayBuffer = this.result;
observer.next(arrayBuffer);
observer.complete();
};
fileReader.readAsArrayBuffer(file);
});
}
I did not notice that the Angular 2's http's PUT was taking the body as string. So, I resorted to using XHR to upload a file with its contents.
var oReq = new XMLHttpRequest();
oReq.open("PUT", url, true);
oReq.setRequestHeader("Content-Type", "text/plain");
oReq.onload = function(e){
console.log('done');
};
oReq.send(arrayBuffer);

How to get the source of an image from upload form?

One of my first larger projects so please bear with me. I have a script which will help me resize an image and turn it into base64. This is how it begins:
var createImage = function (src) {
var deferred = $.Deferred();
var img = new Image();
img.onload = function() {
deferred.resolve(img);
};
img.src = src;
return deferred.promise();
};
And my question is to get the image source from the upload form to the script?
I've tried to stitch together (with help from other sources) a function with the Filereader API:
var createImageURL = function () {
var fileinput = document.getElementById('fileinput');
file = fileinput.files[0];
var reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function (event) {
var blob = new Blob([event.target.result]);
window.URL = window.URL || window.webkitURL;
var blobURL = window.URL.createObjectURL(blob);
}
return blobURL;
};
However this returns a GET error in the console.
Rather than going via Blob, convert your <input>'s File to an ObjectURL directly, saving yourself a lot of trouble by keeping your code synchronous and requiring fewer lines of code.
function inputToURL(inputElement) {
var file = inputElement.files[0];
return window.URL.createObjectURL(file);
}
var url = inputToURL(document.getElementById('fileinput'));
createImage(url);
This works because a File is a Blob per spec (as pointed out by Ray Nicholus)
It's not advised (as File inherits from Blob already) and highly unusual to want to convert between them, but not impossible. I'm including this so you can see how to structure FileReader code if you need it in future, not as a solution to your problem. To convert <input type="file" />'s first file to Blob, you would do
function fileToBlob(inputElement, callback) {
var fileReader = new FileReader();
fileReader.onload = function () {
callback(new Blob([this.result]));
}
fileReader.readAsArrayBuffer(inputElement.files[0]);
}
Where callback takes a Blob as it's first parameter. Remember that since the readAsArrayBuffer caused us to use a callback, we had to write this so it would work in an asynchronus environment.

Show video blob after reading it through AJAX

While I was trying to create a workaround for Chrome unsupporting blobs in IndexedDB I discovered that I could read an image through AJAX as an arraybuffer, store it in IndexedDB, extract it, convert it to a blob and then show it in an element using the following code:
var xhr = new XMLHttpRequest(),newphoto;
xhr.open("GET", "photo1.jpg", true);
xhr.responseType = "arraybuffer";
xhr.addEventListener("load", function () {
if (xhr.status === 200) {
newphoto = xhr.response;
/* store "newphoto" in IndexedDB */
...
}
}
document.getElementById("show_image").onclick=function() {
var store = db.transaction("files", "readonly").objectStore("files").get("image1");
store.onsuccess = function() {
var URL = window.URL || window.webkitURL;
var oMyBlob = new Blob([store.result.image], { "type" : "image\/jpg" });
var docURL = URL.createObjectURL(oMyBlob);
var elImage = document.getElementById("photo");
elImage.setAttribute("src", docURL);
URL.revokeObjectURL(docURL);
}
}
This code works fine. But if I try the same process, but this time loading a video (.mp4) I can't show it:
...
var oMyBlob = new Blob([store.result.image], { "type" : "video\/mp4" });
var docURL = URL.createObjectURL(oMyBlob);
var elVideo = document.getElementById("showvideo");
elVideo.setAttribute("src", docURL);
...
<video id="showvideo" controls ></video>
...
Even if I use xhr.responseType = "blob" and not storing the blob in IndexedDB but trying to show it immediately after loading it, it still does not works!
xhr.responseType = "blob";
xhr.addEventListener("load", function () {
if (xhr.status === 200) {
newvideo = xhr.response;
var docURL = URL.createObjectURL(newvideo);
var elVideo = document.getElementById("showvideo");
elVideo.setAttribute("src", docURL);
URL.revokeObjectURL(docURL);
}
}
The next step was trying to do the same thing for PDF files, but I'm stuck with video files!
This is a filler answer (resolved via the OP found in his comments) to prevent the question from continuing to show up under "unanswered" questions.
From the author:
OK, I solved the problem adding an event that waits for the
video/image to load before executing the revokeObjectURL method:
var elImage = document.getElementById("photo");
elImage.addEventListener("load", function (evt) { URL.revokeObjectURL(docURL); }
elImage.setAttribute("src", docURL);
I suppose the revokeObjectURL method was executing before the video
was totally loaded.

Categories