FileReader not working in Angular 2 - javascript

I'm trying to upload an image using FileReader, It works fine in debug mode (when set breakpoint on the line this.name = Image.files[0].name;), but doesn't work if I deactivate breakpoint. testDetails.image gets set to empty string. I have tried setTimeout also, its also not working.
var fileByteArray = '';
const Image = this.AccUserImage.nativeElement;
if (Image.files && Image.files[0]) {
this.AccUserImageFile = Image.files[0];
}
var fileReader = new FileReader();
fileReader.onload = function (event) {
var imageData = fileReader.result;
var bytes = new Uint8Array(imageData);
//for (var i = 0; i < bytes.length; i++) {
for (var i = 0; i < bytes.length; ++i) {
fileByteArray += (String.fromCharCode(bytes[i]));
}
};
if (fileReader && Image.files && Image.files.length) {
fileReader.readAsArrayBuffer(Image.files[0]);
}
}
this.name = Image.files[0].name;
const ImageFile: File = this.AccUserImageFile;
let length = this.form.value.addresses.length;
this.testList = [];
for (let i = 0; i < length; i++) {
let testDetails = new testDto();
testDetails.image = btoa(fileByteArray);
}

Maybe the test should be at the end of the fileReader.load function because your test depends on fileReader.onload function to be finished at least once so fileByteArray is not undefined.
fileReader.onload = function (event) {
var imageData = fileReader.result;
var bytes = new Uint8Array(imageData);
for (var i = 0; i < bytes.length; ++i) {
fileByteArray += (String.fromCharCode(bytes[i]));
}
if (fileReader && Image.files && Image.files.length) {
fileReader.readAsArrayBuffer(Image.files[0]);
}
for (let i = 0; i < length; i++) {
let testDetails = new testDto();
testDetails.image = btoa(fileByteArray);
}
};

There were some problems in the current implementation, I am posting the working code below. The first problem was that I was using JavaScript style calling for onload function. The second problem was I have to put all the code inside onload function because readAsArrayBuffer is an async call.
var fileByteArray = '';
const Image = this.AccUserImage.nativeElement;
if (Image.files && Image.files[0]) {
this.AccUserImageFile = Image.files[0];
}
var fileReader = new FileReader();
fileReader.onload = (e) => {
var imageData = fileReader.result;
var bytes = new Uint8Array(imageData);
for (var i = 0; i < bytes.length; ++i) {
fileByteArray += (String.fromCharCode(bytes[i]));
}
this.name = Image.files[0].name;
const ImageFile: File = this.AccUserImageFile;
let length = this.form.value.addresses.length;
this.testList = [];
for (let i = 0; i < length; i++) {
testDetails.image = btoa(fileByteArray);
}
}
fileReader.readAsArrayBuffer(Image.files[0]);

Related

JS: How to take new image value from input

I'm trying to get an image from input convert it to array as well to display the new image into the imgPicture.src. However, I'm either getting undefined or empty source. Any possible solution? Thank you in advance.
let changePicInput = document.createElement("input");
changePicInput.type = "file";
changePicInput.id = `file-${finalArray[i].Id}`;
changePicInput.style.display = "none";
changePicInput.addEventListener("change", function () {
let arrBinaryFile = [];
let file = document.getElementById(`file-${materialId}`).files[0];
let reader = new FileReader();
// Array
reader.readAsArrayBuffer(file);
reader.onloadend = function (evt) {
if (evt.target.readyState == FileReader.DONE) {
var arrayBuffer = evt.target.result,
array = new Uint8Array(arrayBuffer);
for (var i = 0; i < array.length; i++) {
arrBinaryFile.push(array[i]);
}
}
}
// Display the image rightaway
imgPicture.src = file.value;
});
Hope it helps!
let imgPicture = document.querySelector('#imgPicture'); // Added the line.
let changePicInput = document.createElement("input");
changePicInput.type = "file";
changePicInput.id = `file-565656`; // Changed the line.
changePicInput.style.display = "block"; // Changed the line.
document.body.appendChild(changePicInput); // Added the line.
changePicInput.addEventListener("change", function () {
let arrBinaryFile = [];
let file = document.getElementById(`file-565656`).files[0]; // Changed the line.
let reader = new FileReader();
// Array
reader.readAsArrayBuffer(file);
reader.onloadend = function (evt) {
if (evt.target.readyState == FileReader.DONE) {
var arrayBuffer = evt.target.result,
array = new Uint8Array(arrayBuffer);
for (var i = 0; i < array.length; i++) {
arrBinaryFile.push(array[i]);
}
}
}
// Display the image rightaway
//imgPicture.src = file.value;
imgPicture.src = URL.createObjectURL(file) // Added the line.
console.log(file); // Added the line.
});
<body>
<img id="imgPicture">
</body>

Loop over uploaded files and return an array of file signatures

I want to loop over files selected for upload, get the file signature and return a array of file signatures. The listOfFileSignatures array is empty outside the readFirstFourBytes function. Is their a way to make it accessible globally?
var listOfFileSignatures = [];
var totalSize;
var uploadedFiles = document.getElementById("notes").files;
for (file of uploadedFiles) {
var blob = file;
var fileReader = new FileReader();
fileReader.onloadend = function readFirstFourBytes(e) {
var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
var fileSignature = "";
for (var i = 0; i < arr.length; i++) {
fileSignature += arr[i].toString(16);
};
listOfFileSignatures.push(fileSignature);
console.log(listOfFileSignatures); // Array(3) [ "ffd8ffdb", "ffd8ffe0", "47494638" ]
};
fileReader.readAsArrayBuffer(blob);
};
console.log(listOfFileSignatures); // Array []
Heres the output
You can declare listOfFileSignatures globally, but the signatures are computed asynchronously, so the list will be empty directly after the for loop. FileReader is always asynchronous, so you can't avoid that. One possibility to handle this is to check if the list is full inside onloadend (listOfFileSignatures.length == uploadedFiles.length) and then do what you want there.
A nicer approach is to use promises, like this:
var uploadedFiles = document.getElementById("notes").files;
Promise.all([...uploadedFiles].map(file => new Promise((resolve, reject) => {
var blob = file;
var fileReader = new FileReader();
fileReader.onloadend = function readFirstFourBytes(e) {
var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
var fileSignature = "";
for (var i = 0; i < arr.length; i++) {
fileSignature += arr[i].toString(16);
};
resolve(fileSignature);
};
fileReader.readAsArrayBuffer(blob);
}))).then(function(listOfFileSignatures) {
// this will be called once, when all results are collected.
console.log(listOfFileSignatures);
});
Additionally, reading all bytes and then select just the first 4 byte is inefficient. Improved version:
Promise.all([...uploadedFiles].map(file => new Promise((resolve, reject) => {
var blob = file;
var fileReader = new FileReader();
fileReader.onloadend = function readFirstFourBytes(e) {
var arr = new Uint8Array(e.target.result);
var fileSignature = "";
for (var i = 0; i < arr.length; i++) {
fileSignature += arr[i].toString(16);
};
resolve(fileSignature);
};
fileReader.readAsArrayBuffer(blob.slice(0, 4));
}))).then(function(listOfFileSignatures) {
// this will be called once, when all results are collected.
console.log(listOfFileSignatures);
});
fileReader.onload is asynchronous, console.log (listOfFileSignatures); is called before files have been read
one option is to create an external function that returns a promise, returning the listOfFileSignatures array
function getListFile() {
return new Promise((resolve, reject) => {
var blob = file;
var fileReader = new FileReader();
fileReader.onloadend = function readFirstFourBytes(e) {
var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
var fileSignature = "";
for (var i = 0; i < arr.length; i++) {
fileSignature += arr[i].toString(16);
};
listOfFileSignatures.push(fileSignature);
resolve(listOfFileSignatures);
};
}
}

Azure Speech javascript SDK: Output audio in mp3

I use the sdk.connection methods to capture audio from the speech to text recognizer. It creates PCM audio that I want to convert into MP3.
This is how connection is initialised:
const con = SpeechSDK.Connection.fromRecognizer(this.recognizer);
con.messageSent = args => {
// Only record outbound audio mesages that have data in them.
if (
args.message.path === "audio" &&
args.message.isBinaryMessage &&
args.message.binaryMessage !== null
) {
this.wavFragments[this.wavFragmentCount++] =
args.message.binaryMessage;
}
};
and this is the wav file build:
let byteCount = 0;
for (let i = 0; i < this.wavFragmentCount; i++) {
byteCount += this.wavFragments[i].byteLength;
}
// Output array.
const sentAudio = new Uint8Array(byteCount);
byteCount = 0;
for (let i = 0; i < this.wavFragmentCount; i++) {
sentAudio.set(new Uint8Array(this.wavFragments[i]), byteCount);
byteCount += this.wavFragments[i].byteLength;
} // Write the audio back to disk.
// Set the file size in the wave header:
const view = new DataView(sentAudio.buffer);
view.setUint32(4, byteCount, true);
view.setUint32(40, byteCount, true);
I tried using lamejs to convert 'sentAudio' into MP3.
import {lamejs} from "../../modules/lame.min.js";
const wavBlob = new Blob([sentAudio]);
const reader = new FileReader();
reader.onload = evt => {
const audioData = evt.target.result;
const wav = lamejs.WavHeader.readHeader(new DataView(audioData));
const mp3enc = new lamejs.Mp3Encoder(1, wav.sampleRate, 128);
const samples = new Int8Array(audioData, wav.dataOffset, wav.dataLen / 2);
let mp3Tmp = mp3enc.encodeBuffer(samples); // encode mp3
// Push encode buffer to mp3Data variable
const mp3Data = [];
mp3Data.push(mp3Tmp);
// Get end part of mp3
mp3Tmp = mp3enc.flush();
// Write last data to the output data, too
// mp3Data contains now the complete mp3Data
mp3Data.push(mp3Tmp);
const blob = new Blob(mp3Data, { type: "audio/mp3" });
this.createDownloadLink(blob, "mp3");
};
reader.readAsArrayBuffer(wavBlob);
MP3 Blob is empty or contains inaudible sounds.
I have also tried using the 'encodeMP3' method described in this example but it gives the same output.
Any existing solutions to support this mp3 conversion ?
Regarding the issue, please refer to the following code.
let byteCount = 0;
for (let i= 0; i < wavFragmentCount; i++) {
byteCount += wavFragments[i].byteLength;
}
// Output array.
const sentAudio: Uint8Array = new Uint8Array(byteCount);
byteCount = 0;
for (let i: number = 0; i < wavFragmentCount; i++) {
sentAudio.set(new Uint8Array(wavFragments[i]), byteCount);
byteCount += wavFragments[i].byteLength;
}
// create wav file blob
const view = new DataView(sentAudio.buffer);
view.setUint32(4, byteCount, true);
view.setUint32(40, byteCount, true);
let wav = new Blob([view], { type: 'audio/wav' });
// read wave file as base64
var reader = new FileReader();
reader.readAsDataURL(wav);
reader.onload = () => {
var base64String = reader.result.toString();
base64String = base64String.split(',')[1];
// convert to buffer
var binary_string = window.atob(base64String);
var len = binary_string.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
// convert to mp3 with lamejs
var wavHdr = lamejs.WavHeader.readHeader(
new DataView(bytes.buffer)
);
console.log(wavHdr);
var wavSamples = new Int16Array(
bytes.buffer,
0,
wavHdr.dataLen / 2
);
let mp3 = this.wavToMp3(
wavHdr.channels,
wavHdr.sampleRate,
wavSamples
);
reader.readAsDataURL(mp3);
reader.onload = () => {
var base64String = reader.result;
console.log(base64String);
};
};
function wavToMp3(channels, sampleRate, samples) {
console.log(channels);
console.log(sampleRate);
var buffer = [];
var mp3enc = new lamejs.Mp3Encoder(channels, sampleRate, 128);
var remaining = samples.length;
var maxSamples = 1152;
for (var i = 0; remaining >= maxSamples; i += maxSamples) {
var mono = samples.subarray(i, i + maxSamples);
var mp3buf = mp3enc.encodeBuffer(mono);
if (mp3buf.length > 0) {
buffer.push(new Int8Array(mp3buf));
}
remaining -= maxSamples;
}
var d = mp3enc.flush();
if (d.length > 0) {
buffer.push(new Int8Array(d));
}
console.log('done encoding, size=', buffer.length);
var blob = new Blob(buffer, { type: 'audio/mp3' });
var bUrl = window.URL.createObjectURL(blob);
console.log('Blob created, URL:', bUrl);
return blob;
}

Can we able to update a particular cell in csv file using Javascript?

Can we able to update a particular cell in csv file using Javascript?
Can anyone share please share the sample javascript code?
Considering you have a workbook, here is how you may loop through the rows and change the cell value:
var rows = workbook.sheets[0].rows;
for (var ri = 0; ri < rows.length; ri++) {
var row = rows[ri];
for (var ci = 0; ci < row.cells.length; ci++) {
var cell = row.cells[ci];
cell.value = new_data;
cell.hAlign = "left";
}
}
Update
var file = document.getElementById('docpicker')
file.addEventListener('change', importFile);
function importFile(evt) {
var f = evt.target.files[0];
if (f) {
var r = new FileReader();
r.onload = e => {
var contents = processExcel(e.target.result);
console.log(contents)
}
r.readAsBinaryString(f);
} else {
console.log("Failed to load file");
}
}
function processExcel(data) {
var workbook = XLSX.read(data, {
type: 'binary'
});
// inject your logic as per need
var rows = workbook.sheets[0].rows;
for (var ri = 0; ri < rows.length; ri++) {
var row = rows[ri];
for (var ci = 0; ci < row.cells.length; ci++) {
var cell = row.cells[ci];
cell.value = new_data;
cell.hAlign = "left";
}
}
};

reader.onload function cant read value neither call function

im using reader.onload event to get contents of csv file,
problem is the value displays in console.log() but not in DOM i.e via binding
dropped(event: UploadEvent) {
this.files = event.files;
console.log(this.files)
for (const droppedFile of event.files) {
// Is it a file?
if (droppedFile.fileEntry.isFile) {
const fileEntry = droppedFile.fileEntry as FileSystemFileEntry;
fileEntry.file((file: File) => {
// Here you can access the real file
console.log(droppedFile.relativePath, file);
const fileToRead = file;
const fileReader = new FileReader();
fileReader.onload = this.onFileLoad;
fileReader.readAsText(fileToRead);
console.log(this.tempval) /// undefined
});
}
}}
and onFileLoad function is as follows
onFileLoad(fileLoadedEvent) {
const textFromFileLoaded = fileLoadedEvent.target.result;
this.csvContent = textFromFileLoaded;
var allTextLines = this.csvContent.split(/\r\n|\n/);
var headers = allTextLines[0].split(',');
var lines = [];
for ( var i = 0; i < allTextLines.length; i++) {
// split content based on comma
var data = allTextLines[i].split(',');
if (data.length == headers.length) {
var tarr = [];
for ( var j = 0; j < headers.length; j++) {
tarr.push(data[j]);
}
lines.push(tarr);
}
}this.tempval = linesconsole.log(this.tempval) // printing value
};
unfortunately data inside this.tempval is not accessible anywhere
not in html DOM or inside dropped() funtion. except inside onFileLoad()
im just new to typescript
thanks in advance

Categories

Resources