Let's say I want to upload 2 images to an ajax, I will send them using this format
{ "base64StringName:" : "[ {"1": "base64_1"}, {"2" : "base64_2"} ]"}
So its an object that contains an array of objects of base64 strings
To do so, I will need to create an array and inside this array, I will push json objects into it.
Here is my code for this:
<script>
var test ='';
var imageArray =[];
var imageObject ={};
$('#inputFileToLoad').on('change', function(){
imageArray.length = 0;
fileCount = this.files.length;
for(i = 0; i < fileCount; i++){
var file = document.querySelector('#inputFileToLoad').files[i];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
test = reader.result.split(',')[1];
console.log(test);
imageObject[i] = test;
imageArray.push(imageObject);
};
reader.onerror = function (error) {
alert('Error: ', error);
};
}
});
$('#inputFileToLoadButton').on('click', function(){
console.log(imageArray);
$.ajax({
url:"some url",
method:"POST",
data: {
"base64String": imageArray
}
,success: function () {
swal("Success!","Upload Finished!","success");
//add redirect!
},
error: function (jqXHR) {
swal("Error",jqXHR.responseText, "error");
}
});
});
</script>
However, I encounter a problem, my first object inside the array somehow gets overwritten.
it becomes
{ "base64StringName:" : "[ {"1": "base64_2"}, {"2" : "base64_2"} ]"}
Also when i printed out the first base64 encoded file at console.log(test); it is undefined, but when i printed out the second base64 encoded file, it prints the second file only.
try this:
var test = '';
var imageArray = [];
var imageObject;
$('#inputFileToLoad').on('change', function() {
imageArray.length = 0;
fileCount = this.files.length;
for (i = 0; i < fileCount; i++) {
debugger;
var file = document.querySelector('#inputFileToLoad').files[i];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function() {
test = this.result.split(',')[1];
imageObject = {};
imageObject[index] = test;
imageArray.push(imageObject);
}.bind({
index: i
});
reader.onerror = function(error) {
alert('Error: ', error);
};
}
});
Related
I'm looking to retrieve data from a local CSV file, store it in an Object, then send it via an API. But when I try to display data[i].id; to see if I can get a value, it is undefined.
I use ya-csv to parse the CSV file.
myFile.csv
id;name;email;
1;John;john#doe.com
2;Jane;jane#doe.com
csvParser.js
const csv = require('ya-csv');
const data = [];
const file = 'myFile.csv';
function loopForPrint() {
for (var i = 0; i < data.length; i++) {
let id = data[i].id;
console.log(id);
}
}
function csvToJson() {
var reader = csv.createCsvFileReader(file, {columnsFromHeader: true, 'separator': ';'});
reader.addListener('data', function(data) {
data.push(data);
loopForPrint();
})
reader.addListener('end', function() {
console.log('end');
});
};
First of all, you can remove the tailing ; so that there won't be an empty key and undefined value
Secondly, you can replace this code with
reader.addListener('data', function(data) {
data.push(data);
loopForPrint();
})
this one
reader.addListener('row', function(row) {
data.push(row);
loopForPrint();
})
as data is defined globally and locally will create a conflict
Here is the complete code
const csv = require('ya-csv');
const data = [];
const file = 'myFile.csv';
function loopForPrint() {
for (var i = 0; i < data.length; i++) {
console.log(data[i].id);
}
}
function csvToJson() {
var reader = csv.createCsvFileReader(file, {columnsFromHeader: true, 'separator': ';'});
reader.addListener('data', function(row) {
data.push(row);
})
reader.addListener('end', function() {
loopForPrint();
console.log('end');
});
};
csvToJson()
Output
1
2
end
I have also created StackBlitz for this if you want to look at it
I am working on reading .csv /xlsx file uploaded using javaScript and get the result as array containing each row . I was able to read the file and get data using FileReader and SheetJs with following code.
// code for the new excel reader
$scope.do_file = function(files)
{
$scope.fileContent = [];
var X = XLSX;
var global_wb;
var f = files[0];
var reader = new FileReader();
reader.onload = function(e)
{
var data = e.target.result;console.log(data);
global_wb = X.read(data, {type: 'array'});
var output = "";
var result = {};
global_wb.SheetNames.forEach(function(sheetName) {
var roa = X.utils.sheet_to_json(global_wb.Sheets[sheetName], {header:1});
if(roa.length) result[sheetName] = roa;
});
$scope.fileContent = result["Sheet1"];
if(!result["Sheet1"])
{
$scope.fileContent = result["contacts"].filter(function(el) { return typeof el != "object" || Array.isArray(el) || Object.keys(el).length > 0; });
}
};
reader.readAsArrayBuffer(f);
};
For reading most of the files the code works , but when file containing Hebrew text with Windows-1255 encoding i get gibberish data.
Looking in for more options i tried to read the file as text using reader.readAsText and change the encoding as necessary , check the following code:
function is_Hebrew(data)
{
var position = data.search(/[\u0590-\u05FF]/);
return position >= 0;
}
$scope.do_file = function(files)
{
var fullResult = [];
var file =files[0];
var reader = new FileReader();
reader.onload = function(e){
var data = e.target.result;
if(!is_Hebrew(data.toString()))
{
reader.readAsText(file,'ISO-8859-8');
}
};
reader.readAsText(file);
reader.onloadend = function(){
var lines = reader.result.split('\r\n');
console.log(lines);
lines.forEach(element => {
var cell = element.split(',');
fullResult.push(cell);
});
console.log(reader);
};
};
but the above code is not suitable as it does not read the file as each row identifying each cell. if any one of cell contains string with coma separated value (for example if a cell contains a string value such as "25,28,29" ) the array output gives wrong data as it considers each values as each cell.
So i decided to stick with first method but i am not able to change the encoding .Is there a possible way to change encoding in the first code where i have used the readAsArrayBuffer to read the file data ?
After going through lot of possible solutions i found that answer to the above question was to combine the above two methods. The first method for reading the xlsx files and second method for reading csv files. Also i have used an additional javaScript library called papaparse in the second method to solve the problem of reading data in each cell
$scope.is_Hebrew = function($data){
var position = $data.search(/[\u0590-\u05FF]/);
return position >= 0;
}
// code for the new excel reader
$scope.do_file = function(files)
{
var config = {
delimiter: "", // auto-detect
newline: "", // auto-detect
quoteChar: '"',
escapeChar: '"',
header: false,
trimHeader: false,
dynamicTyping: false,
preview: 0,
encoding: "",
worker: false,
comments: false,
step: undefined,
complete: undefined,
error: undefined,
download: false,
skipEmptyLines: false,
chunk: undefined,
fastMode: undefined,
beforeFirstChunk: undefined,
withCredentials: undefined
};
$scope.fileContent = [];
var f = files[0];
var fileExtension = f.name.replace(/^.*\./, '');
if(fileExtension == 'xlsx')
{
var X = XLSX;
var global_wb;
var reader = new FileReader();
reader.onload = function(e)
{
var data = e.target.result;
global_wb = X.read(data, {type: 'array'});
var result = {};
global_wb.SheetNames.forEach(function(sheetName) {
var roa = X.utils.sheet_to_json(global_wb.Sheets[sheetName], {header:1});
if(roa.length) result[sheetName] = roa;
});
$scope.fileContent = result["Sheet1"];
if(!result["Sheet1"])
{
$scope.fileContent = result["contacts"].filter(function(el) { return typeof el != "object" || Array.isArray(el) || Object.keys(el).length > 0; });
}
};
reader.readAsArrayBuffer(f);
}
else if(fileExtension == 'csv')
{
var reader = new FileReader();
reader.onload = function(e)
{
var data = e.target.result;
console.log(f);
console.log($scope.is_Hebrew(data.toString()));
if(!$scope.is_Hebrew(data.toString()))
{
reader.readAsText(f,'ISO-8859-8');
}
};
reader.readAsText(f);
reader.onloadend = function(e){
var c = Papa.parse(reader.result,[ config])
console.log(c);
$scope.fileContent = c["data"].filter(function(el) { return typeof el != "object" || Array.isArray(el) || Object.keys(el).length > 0; });
};
}
else
{
alert("File Not supported!");
}
$scope.fileContent.push([]);
};
Here i have two form fields , in this i want to convert the base 64 encode from image,and after that i want to pass in JSON Format to next URL, i tried like this but i am not getting ,some time i am getting one filed value (encoded value) uncaught error property_img , i don't know how to do anyone help me pls
var files = document.getElementById('floorplan_img').files;
if (files.length > 0) {
var file = files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function() {
console.log(reader.result);
var base64 = reader.result;
var str = base64;
var arr = str.split(",");
var floor_img = arr[1];
console.log(floor_img);
};
reader.onerror = function(error) {
console.log('Error: ', error);
};
}
var files1 = document.getElementById('upload_properties').files;
if (files1.length > 0) {
var file1 = files1[0];
var reader1 = new FileReader();
reader1.readAsDataURL(file1);
reader1.onload = function() {
var base64_img = reader1.result;
var str_64 = base64_img;
var arr_str = str_64.split(",");
var property_img = arr_str[1];
console.log(property_img);
};
reader1.onerror = function(error) {
console.log('Error: ', error);
};
}
<input type="file" id="floorplan_img">
<input type="file" id="upload_properties">
Try this:
var reader = new FileReader();
reader.onload = function(event) {
var src= event.target.result;
console.log(src);
};
So I have a website where the user puts a .csv file into a website and the website extracts it into a list in JavaScript. The full code that I am doing is to compare a .csv file that the user inputs into a website with the .csv file the website currently has. I want to be able to compare the two different files outside the function that I have below.
var a = [];
function compare(file) {
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function(event) {
var csv = event.target.result;
var data = $.csv.toArrays(csv);
number = data.length;
for (i = 1; i < data.length; i++) {
a.push({date: data[i][0], url: data[i][5], count: data[i][6]});
};
reader.onerror = function() {
alert('Unable to read ' + file.fileName);
};
}
var para = document.createElement("p");
var node = document.createTextNode(a[0].url);
para.appendChild(node);
var element = document.getElementById("demo");
element.appendChild(para);
At the end of this code snippet, I was testing to see if I can call upon the contents of the list a. However, I keep getting an "Uncaught TypeError: Cannot read property 'url' of undefined".
The error occurs at
var node = document.createTextNode(a[0].url);"
I think the problem is the async nature of the FileReader
function compare(file, callback) {
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function (event) {
var a = [];
var csv = event.target.result;
var data = $.csv.toArrays(csv);
number = data.length;
for (i = 1; i < data.length; i++) {
a.push({
date: data[i][0],
url: data[i][5],
count: data[i][6]
});
callback(a);
};
}
//misplaced it in the onload handler
reader.onerror = function () {
alert('Unable to read ' + file.fileName);
};
}
then need to use the callback to access a
//here compare is an async method so to use the value of a after calling compare we will have to depend on a callback
compare(e.target.files[0], function (a) {
var para = document.createElement("p");
var node = document.createTextNode(a[0].url);
para.appendChild(node);
var element = document.getElementById("demo");
element.appendChild(para);
});
Demo: Fiddle
How can I get the return value of that.whatever back from the closure? Instead of:
this.setCanvas = function(files){
var numItems = files.length - 1;
this.items = {};
var i = 0;
for(i=0;i<=numItems;i++)
{
var file = files[i];
var reader = new FileReader();
reader.onload = (function(i) {
return function(e) {
var something = that.whatever();
items[i] = something;
};
})(i);
reader.readAsDataURL(file);
}
console.log(items);
}
I need items[i] defined. If I console.log items[i] outside of the closure it is undefined.
The problem isn't the closure; it's the callback. Whatever needs to use the value of that.whatever needs to be executed in the callback.
You can augment your code to keep track of the number of files loaded. This way, when the last file has been loaded, you can invoke an ultimate completion handler:
this.setCanvas = function(files) {
var numItems = files.length - 1;
var itemsLoaded = 0; // Initialize to zero
var items = [];
var i = 0;
for(i=0;i<=numItems;i++) {
var file = files[i];
var reader = new FileReader();
reader.onload = (function(i) {
return function(e) {
var something = that.whatever();
items[i] = something;
if(++itemsLoaded == numItems) {
// At this point all files will have been loaded.
allLoaded();
}
};
})(i);
reader.readAsDataURL(file);
}
function allLoaded() {
// Now we can analyze the results
console.log(items);
}
}
I also changed items to be an Array instead of an Object.
Also if you want to be a little more clever, you could decrement numItems and check for zero instead of creating a new itemsLoaded variable.
There are a couple things you need to change here. First set this.items to an array. Next assign this to self so it can be referenced in the closure. Next assign the something to self.items[i] instead of items[i]. Finally use this.items in the console.log
this.setCanvas = function(files){
var self = this;
var numItems = files.length - 1;
this.items = [];
var i = 0;
for(i=0;i<=numItems;i++)
{
var file = files[i];
var reader = new FileReader();
reader.onload = (function(i) {
return function(e) {
var something = that.whatever();
self.items[i] = something;
};
})(i);
reader.readAsDataURL(file);
}
console.log(this.items);
}