I am using FileReader in my web app to read a user-selected local file, and when I readAsText() the readyState should change to '2' once completed. Here is the code I have:
var fr = new FileReader(); // readyState is 0
var filetoload = $("#foo")[0].files[0];
fr.readAsText(filetoload); // readyState should be 2!!
var xml = fr.result;
localStorage.setItem('foo', xml);
Now in Firefox, this all works fine and the xml gets written to the localStorage just fine. If I do this Chrome in the console at a resting state (assuming there is a file specified in the #foo input) then it works as well. BUT if I run this normally from the script tag in my .jsp file, readyState = 1 (!) after line 3 above. AND, if I put a breakpoint on line 3, then try to readAsText() from the console, it sets readyState = 1 as well.
What does Chrome need to fully read the file during execution? What am I doing wrong? The fact that it works in Firefox and Chrome only during a resting state in the console leads me to believe there is something more that Chrome needs to allow this or something. Any insight is appreciated, thanks.
I was able to find an answer from this post. Since reading the file happens asynchronously, I guess I needed to handle accordingly. Below is what worked for me. (jsonCall() is just an internal function we have that basically calls $.ajax) I hope this helps someone in the future.
$(document).ready(function(){
$('#foo').on('click', function(e){
readFile($("[name='filelocation']")[0].files[0], function(e) {
// use e.target.result in callback...
var data = { "xml" : e.target.result };
jsonCall("myservlet", data, function() {
window.open(url, "_blank", "height=800,width=1200");
})
});
});
});
function readFile(file, onLoadCallback)
{
var fr = new FileReader();
fr.onload = onLoadCallback;
fr.readAsText(file);
}
Related
My FileReader object is working perfectly to upload images. I'm tracking onload as well as other events, these all happen when I upload images:
fileReader = new FileReader();
fileReader.onloadstart = (e) => {
window.alert('fileReader onloadstart');
window.alert(e);
};
// ... and the same for onprogress, onabort, onerror, then finally:
fileReader.onload = (e) => {
window.alert('arrived to fileReader.onload!');
// ...
};
I added cordova-plugin-media-capture to capture audio. I now need to use the existing fileReader.onload callback to upload it etc.
But no matter what I do, I cannot get fileReader.readAsDataURL to respond. Below is my code adapted from this answer about a similar problem, but it doesn't resolve it.
None of the fileReader events are firing, not even error. The fileReader.readAsDataURL function is available, yet when calling it all that happens is the screen briefly goes white and then I'm back at the page I was at before as if I had not done anything. None of the methods on fileReader show their alerts.
navigator.device.capture.captureAudio((files) => {
const file = files[0];
newFile = new File(
file.name,
file.localURL,
file.type,
file.lastModifiedDate,
file.size);
window.alert(newFile);
// --> [Object object]
window.alert(JSON.stringify(newFile));
// --> An object with name, localURL etc. See image.
window.alert(fileReader.readAsDataURL);
// --> function readAsDataURL() { [native code] }
fileReader.readAsDataURL(newFile); // nothing at all
})
The stringified newFile object is:
I've tried processing the file captureAudio gives in different ways:
resolveLocalFileSystemURL: https://ourcodeworld.com/articles/read/80/how-to-convert-a-image-from-the-device-to-base64-with-javascript-in-cordova
fileSystem.root.getFile as in https://groups.google.com/forum/#!msg/phonegap/uX_aDRKp72I/ZUbt0ThWVQkJ
But every time the same thing: when I arrive at readAsDataURL, nothing happens anymore. What could be wrong?
Edit: I forgot to mention some things:
tested on iOS device and simulator
cordova-plugin-file is installed
I'm currently writing a Chrome extension that needs to save some images into chrome.storage memory. I'm currently making an array of objects:
var AnImage = new Image()
AnImage.src = http://image.image/imageurl.png
var ObjectToSave = { ...,
graph_img : AnImage,
... }
...
AnArray[x] = ObjectToSave
I output with a simple append
document.getElementById("AnElement").appendChild(ObjectToSave.graph_img)
But when I load it from storage and try to append it again, it returns an error
Error in response to storage.get: TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
When I output it through console.log() it evaluates what has been retrieved as an object, but not anything I can recognise. I'm currently using chrome.storage.sync
Is there a way of doing this? There seems to be little help in the way of storing images, and of what exists is old and talks about encoding with base64 for the older storage API. But when I did my initial research there were people claiming that base64 encoding was no longer necessary
After more looking, I found out about the FileReader object that provides a more elegant way over using the canvas method. And as this is chrome specific compatibility is ensured.
function ImageLoader( url ){
var imgxhr = new XMLHttpRequest();
imgxhr.open( "GET", url + "?" + new Date().getTime() );
imgxhr.responseType = "blob";
imgxhr.onload = function (){
if ( imgxhr.status===200 ){
reader.readAsDataURL(imgxhr.response);
}
};
var reader = new FileReader();
reader.onloadend = function () {
document.getElementById( "image" ).src = reader.result;
chrome.storage.local.set( { Image : reader.result } );
};
imgxhr.send();
}
Using chrome.storage.local is needed as it is highly likely that the storage size limit for chrome.storage.sync will be exceeded.
As Marc Guiselin and wOxxOm mentioned in the comments, chrome.storage will serialize the data first, to save image, you could:
Save the image src. chrome.storage.sync.set({ src: img.src });
Save the image dataURL.
I don't quite understand what is happening in the following code, if someone can guide me to the right direction maybe it will be easier for me to get the same variable as in the else statement but manually (in case FileReader api isn't supported).
Basicly in my if statement I want to make an ajax call and transform the picture to the base64 string and save it to the read variable same structure as in my else statement:
$('#file').on('change', function(){
if(typeof FileReader === "undefined") {
//AJAX CALL HERE
}
else {
var reader = new FileReader();
}
reader.onload = function(e) {
options.imgSrc = e.target.result;
cropper = $('.imageBox').cropbox(options);
}
reader.readAsDataURL(this.files[0]);
this.files = [];
console.log(reader);
})
console log for the read variable in the else statement shows: Picture
You can't do that without some kind of Polyfiller, the reason being that Javascript (without the FileReader API) cannot handle files and cannot pass them about. You will not be able to send the file to the server with Javascript.
There are 2 ways you can do this :
Cause a postback to occur in which you get the file on the server
and then convert it to Base64 (can be done in PHP/ASP.NET (and
probably lots of others))
Or you can use a Polyfiller such as
moxie, this will load when the
page loads and if File API is not supported it will add a
Flash/Silverlight plugin to mimick the support.
I'm trying to display an image before uploading it via javascript / jQuery.
I'm executing this code in the ADD-Method of the jQuery Fileuploader. The data-attribute provides me with the file
var reader = new FileReader();
reader.onload = function(e) {
var img = $('<img></img>');
img.attr('src', e.target.result);
$("#general_dropable").append(img);
}
reader.readAsDataURL(file); // Retrieved from the data-attribute of the ADD-Method of the jQuery Fileuploader
Displaying works fine. When I drag the image in Google-Chrome, however, I'm getting this error from Chrome:
He's dead, Jim! Either Chrome ran out of memory or the process for the webpage was terminated for some other reason. To continue, reload or go to another page.
Dragging the image in Firefox works fine.
The image source is the actual source code of the image, not an absolute path.
Is there a workaround to this bug?
Thank you very much.
Edit
You can see a live example here:
http://jsfiddle.net/Fractaliste/LvsYc/1669/
Just drag the image after uploading and the error will appear (In Chrome)
I just found this question on stackoverflow. But looking at the jsfiddle I don't get this exception in Chrome any more (Chrome 46). To me it looked like you forgot to define the "file" variable in your function when you write it to the DOM (reader.readAsDataURL). But in your jsfiddle it seems fixed:
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#target').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
.. this is not my answer as it was fixed already in jsfiddle ... but as I was searching for a solution for my problem i wanted to clarify things here as this might help others.
I'm using Phonegap to download an archive, unzip it, then read the files. It's all working until I try and read the files as text. If I use readAsDataURL() then I get a whole heap of stuff logged to the console.
function( file ) {
console.log(file);
var reader = new FileReader();
reader.onloadend = function( evt ) {
console.log( evt.target.result );
};
reader.readAsDataURL( file );
}
If I use readAsText() I get null. The files range from 300KB to 1.4MB, but all files return null in the console.
reader.readAsText( file );
Why would one function return something and the other be null? Is there a limit on the text size it can read?
This is the file object that I'm logging before creating reader, that I'm applying the functions to (I've shortened the file name):
{
"name":"categories.json",
"fullPath":"/var/mobile/.../Documents/data/file.json",
"type":null,
"lastModifiedDate":1380535318000,
"size":382456
}
And this is the evt object for readAsText():
{
"type":"loadend",
"bubbles":false,
"cancelBubble":false,
"cancelable":false,
"lengthComputable":false,
"loaded":0,
"total":0,
"target":{
"fileName":"/var/mobile/.../Documents/data/file.json",
"readyState":2,
"result":"null",
"error":null,
"onloadstart":null,
"onprogress":null,
"onload":null,
"onerror":null,
"onabort":null
}
}
UPDATE: I've seen in the W3C spec for the File API that result would only be set to null if an error had occured. But I tried adding a reader.onerror() function, but that wasn't getting called.
If an error occurs during reading the blob parameter, set readyState
to DONE and set result to null. Proceed to the error steps.
http://www.w3.org/TR/FileAPI/#dfn-readAsText
You may have been grabbing the fileEntry instead of a fileObject. Assuming file was actually fileEntry, try this:
var
fileEntry = file, //for example clarity - assumes file from OP's file param
reader = new FileReader()
;
fileEntry.file( doSomethingWithFileObject );//gets the fileObject passed to it
function doSomethingWithFileObject(fileObject){
reader.onloadend = function(e){
doSomething(e.target.result); //assumes doSomething defined elsewhere
}
var fileAsText = reader.readAsText(fileObject);
}
Definitely an API that screams for cruft reduction.