I'm trying to read a JSON file I have, uploaded by the user, and try to copy it to an array. However, with a .readAsText(), the return I get has the formatting of a string (obviously), such as including \" and \n and other string-like properties.
Is there a way I can use FileReader (or any other form of reading files, that don't involve a server) to read the JSON file and have it return just the plain JSON?
For example, having it return
[
{"hello": "world"}
]
or
[{"hello": "world"}]
and not
"[\n{\"hello\": \"world\"}\n]"
?
Edit: I am now aware of the JSON.parse(text) method, but I'm getting an error when parsing the FileReader object
let fileUploaded = new FileReader();
fileUploaded.readAsText(MY_JSON_FILE);
console.log(JSON.parse(fileUploaded));
it returns the error error TS2345: Argument of type 'FileReader' is not assignable to parameter of type 'string'
Can I get what i read with FileReader to another var that is a string, and then parse that new var?
The code at the question uses FileReader incorrectly.
FileReader .readAs<Type> operation is asynchronous. FileReader has load and loadend events where the result property of event.target and FileReader instance is the resulting asynchronously processed data.
Do not parse the FileReader object itself.
.readAs<Type> expects a Blob to be passed as parameter, not a JavaScript plain object.
const MY_JSON_FILE = [{
"hello": "world"
}];
let json = JSON.stringify(MY_JSON_FILE);
const blob = new Blob([json], {type:"application/json"});
const fr = new FileReader();
fr.addEventListener("load", e => {
console.log(e.target.result, JSON.parse(fr.result))
});
fr.readAsText(blob);
Related
I've got a blob of audio data confirmed to play in the browser but fails to play after storing, retrieving, and conversion of the same data. I've tried a few methods without success, each time returning the error:
Uncaught (in promise) DOMException: Failed to load because no supported source was found
Hasura notes that bytea data must be passed in as a String, so I tried a couple things.
Converting the blob into base64 stores fine but the retrieval and playing of the data doesn't work. I've tried doing conversions within the browser to base64 and then back into blob. I think it's just the data doesn't store properly as bytea if I convert it to base64 first:
// Storing bytea data as base64 string
const arrayBuffer = await blob.arrayBuffer();
const byteArray = new Uint8Array(arrayBuffer);
const charArray = Array.from(byteArray, (x: number) => String.fromCharCode(x));
const encodedString = window.btoa(charArray.join(''));
hasuraRequest....
`
mutation SaveAudioBlob ($input: String) {
insert_testerooey_one(
object: {
blubberz: $input
}
) {
id
blubberz
}
}
`,
{ input: encodedString }
);
// Decoding bytea data
const decodedString = window.atob(encodedString);
const decodedByteArray = new Uint8Array(decodedString.length).map((_, i) =>
decodedString.charCodeAt(i)
);
const decodedBlob = new Blob([decodedByteArray.buffer], { type: 'audio/mpeg' });
const audio4 = new Audio();
audio4.src = URL.createObjectURL(decodedBlob);
audio4.play();
Then I came across a Github issue (https://github.com/hasura/graphql-engine/issues/3336) suggesting the use of a computed field to convert the bytea data to base64, so I tried using that instead of my decoding attempt, only to be met with the same error:
CREATE OR REPLACE FUNCTION public.content_base64(mm testerooey)
RETURNS text
LANGUAGE sql
STABLE
AS $function$
SELECT encode(mm.blobberz, 'base64')
$function$
It seemed like a base64 string was not the way to store bytea data, so I tried converting the data to a hex string prior to storing. It stores ok, I think, but upon retrieval the data doesn't play, and I think it's a similar problem as storing as base64:
// Encoding to hex string
const arrayBuffer = await blob.arrayBuffer();
const byteArray = new Uint8Array(arrayBuffer);
const hexString = Array.from(byteArray, (byte) =>
byte.toString(16).padStart(2, '0')
).join('');
But using the decoded data didn't work again, regardless of whether I tried the computed field method or my own conversion methods. So, am I just not converting it right? Is my line of thinking incorrect? Or what is it I'm doing wrong?
I've got it working if I just convert to base64 and store as a text field but I'd prefer to store as bytea because it takes up less space. I think something's wrong with how the data is either stored, retrieved, or converted, but I don't know how to do it. I know the blob itself is fine because when generated I can play audio with it, it only bugs out after fetching and attempted conversion its stored value. Any ideas?
Also, I'd really like to not store the file in another service like s3, even if drastically simpler.
I have been working on a project, I download a zip file from internet through XMLHttpRequest (type: blob ) and then I try to read its content using JSzip.So every zip has a json which I am interested in say manifest.json. So I was successful to read it with this code.
var read_zip = new JSZip();
res=xhr.response;
read_zip.loadAsync(xhr.response).then(function (zip) {
return zip.file("manifest.json").async("string");
}).then(function (text) {
obj = JSON.parse(text);
console.log(text);});
after this I made some changes to 'obj', Now I want to replace the existing manifest with this modified 'obj' json contents and save it.
I was trying this code
var write_zip = new JSZip();
write_zip.loadAsync(xhr.response).then(function (zip) {
zip.file("manifest.json" , obj) ;
zip.generateAsync({type:"blob"})
.then(function (blob) {
saveAs(blob, "hello.zip");
});});
but I am getting this error
Uncaught (in promise) Error: Can't read the data of 'manifest.json'.
Is it in a supported JavaScript type (String, Blob, ArrayBuffer, etc)
?
sorry, I am new to this.
It looks like you're trying to write an object into zip which is not supported. According to the documentation on JsZip the value to be written needs to be of type:
String/ArrayBuffer/Uint8Array/Buffer/Blob/Promise/Nodejs stream
See: JSZip#file(name, data [,options])
I'm trying to convert a File into a Blob without using FileReader. I can't use FileReader because the latest version of Typescript (which I must use) doesn't accept a File as the parameter to fileReader.readAsArrayBuffer().
Using FileReader I can do it as follows:
var reader = new FileReader();
reader.onloadend = function(e) {
new Blob([ this.result ], { type: "image/jpeg" } );
};
reader.readAsArrayBuffer(file);
How can I achieve the same result without FileReader?
You can always augment the declaration in lib.d.ts with an overload accepting a File.
For example, create a file named globals.d.ts with the following content
interface FileReader {
readAsArrayBuffer(file: File): void;
}
That said, if the declaration was changed, I would be wary of this behavior as some environments likely do not support it.
In my Javascript, I have a File object using input type file, so I can get file name, file size, etc. How do I get the File's actual data?
You need to address the raw data by looking back to the Blob object. See here:
https://developer.mozilla.org/en-US/docs/Web/API/Blob
You can use a FileReader object, e.g.
function readFile(thefile) {
var reader = new FileReader();
reader.onload = function(e) {
alert(e.target.result);
};
reader.readAsText(thefile);
}
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.