readAsDataURL does not process file from captureAudio - javascript

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

Related

HTML5 Filereader always returns empty string?

I'm just learning how to use the filereader now, and I duplicated an example I found online to experiment with, but for some reason, the filereader always returns an empty string.
First, I have an HTML form for the user to select a file, which then calls the script:
<input type="file" id="filelist" onchange="selectfile()">
Here's the script:
function selectfile() {
myFile = document.getElementById("filelist").files[0];
reader = new FileReader();
reader.readAsText(myFile);
myResult = reader.result;
alert(myFile.name);
alert(myResult);
alert(reader.error);
}
I have tried this with a number of different text files I typed up in Notepad, and in every case the results are the same. I'm only ever submitting one file through the html form.
The 3 alerts are for testing.
It displays the file name correctly.
It displays an empty string for the result.
It displays NULL for the error so it's not getting an error.
I searched around to see if there was something obvious here already, but couldn't find anything that seemed to point me in the right direction.
Thoughts?
The FileReader object is not ready yet. You need to add an onload event listener to the reader and then make a call to the readAsText method. You can then access the file contents from inside the callback function.
MDN docs - https://developer.mozilla.org/en-US/docs/Web/API/FileReader/result
function selectfile() {
myFile = document.getElementById("filelist").files[0];
reader = new FileReader();
reader.onload = () => {
myResult = reader.result;
alert(myFile.name);
alert(myResult);
alert(reader.error);
};
reader.readAsText(myFile); // only accessible when the FileReader is loaded
}
<input type="file" id="filelist" onchange="selectfile()">

FileReader readyState is stuck at 1 when loading a file in Chrome

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);
}

How can I get the same data structure as FileReader API manually

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.

overwrite a file with HTML5 FileWriter

I'm using HTML5 FileWriter API to save the state of my webapp. I have bit of JS that periodically calls FileWriter.write to do that (so , over time, the write method is called several times). By default FileWriter API use an 'append' approach to writing files which does not suits my needs since I wan't to overwrite the file content.
I first tried this:
this._writer.seek(0);
this._writer.write(content);
This is not working when you are writing a text shorter than the file content. I then tried this:
this._writer.truncate(0);
this._writer.write(content);
This code is supposed to clear the file and then write my new content but I'm getting the following error when write method is called:
Uncaught InvalidStateError: An operation that depends on state cached in an interface object was made but the state had changed since it was read from disk.
Odd thing: when I debug the code (with a breakpoint), the error does not occur, as if FileWriter.truncate was an asynchronous method...
I am stuck here, any ideas?
I am using Chrome 30.0.1599.69
Here is a correct code that won't waste 500ms on waiting
fileWriter.onwriteend = function() {
if (fileWriter.length === 0) {
//fileWriter has been reset, write file
fileWriter.write(blob);
} else {
//file has been overwritten with blob
//use callback or resolve promise
}
};
fileWriter.truncate(0);
You can truncate and then write with two different FileWriter objects.
fileEntry.createWriter(function (fileWriter) {
fileWriter.truncate(0);
}, errorHandler);
fileEntry.createWriter(function (fileWriter) {
var blob = new Blob(["New text"], { type: 'text/plain' });
fileWriter.write(blob);
}, errorHandler);
If you want to always override it, you can use this method
function save(path,data){
window.resolveLocalFileSystemURL(dataDirectory, function(dir){
dir.getFile(path, {create:true}, function(file){
file.createWriter(function(fileWriter){
fileWriter.seek(0);
fileWriter.truncate(0);
var blob = new Blob([data], {type:'text/plain'});
fileWriter.write(blob);
}, function(e){
console.log(e);
});
});
});
};
A workaround is the following code:
this._writer.truncate(0);
window.setTimeout(function(){
this._writer.write(content);
}.bind(this),500)
This simply wait 500 milliseconds before writing. Not great but it works...
This is the simplest way how i use to delete the content of a file with syncFileSystem in my Chrome App.
Two createWriter, the first one truncates then the second one overwrites with nothing (you can change with your new value) :
file.createWriter((fileWriter)=>fileWriter.truncate(0));
file.createWriter((fileWriter)=> {
fileWriter.onwriteend = function() {
console.log('New Actions!');
};
var blob = new Blob([''], {type: 'text/plain'});
fileWriter.write(blob);
});

Phonegap FileReader readAsText returns null but readAsDataURL works

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.

Categories