Sync a FileReader in a for loop: Javascript - javascript

I am trying to implement a JavaScript program to read a bunch of CSV files from a particular directory containing sub-directories. To do so, I am thinking of using Javascript to read multiple files using webkitdirectory and reading the files and then using java to push them.
HTML Form
<input id="csv" type="file" multiple webkitdirectory directory>
<input type="button" onclick="readCSV()" value="Submit">
JavaScript to Read Files
function readCSV(){
var fileInput = document.getElementById("csv");
var fileCount = fileInput.files.length;
if( fileCount != 0) {
alert(fileCount);
var reader;
for (var i = 0; i < fileCount; i++) {
reader = new FileReader();
reader.onload = function () {
document.getElementById('out').innerHTML = reader.result;
// Once the file is read, Send it to JavaServlet to save on server.
};
reader.readAsBinaryString(fileInput.files[i]);
}
} else {
alert("Select a File");
}
}
The problem I am facing here is that the code runs successfully when only one file is selected but breaks when multiple files are selected. I think the problem is in sync read. But I couldn't find a way to either sync read or pause the loop while the reader object completely reads the file.

Related

Displaying preview of multiple selected files in Angular

I am kind of new to Angular and right now I am trying to select multiple files and display their preview before uploading them to server.
My below code works fine if there are multiple files but selected separately, hovewer while trying to select multiple images at once, only the last one is rendered. I checked with console.log and while selecting multiple files at once the reader.result of the previous files except the last one is always null ever though the reader.onload is executing (the object is also inserted into the array, but without the image url).
I want to be able to also remove the selected files, so both files and their imagesUrl are kept in an FileWithImage object to keep the right order of their previews.
component.ts:
onFilesSelected(event: any): void {
this.selectedFiles = event.target.files;
for (let i = 0; i < this.selectedFiles.length; i++) {
let fileWithImage: FileWithImage = {
imageUrl: '',
file: this.selectedFiles[i],
};
var reader = new FileReader();
reader.readAsDataURL(fileWithImage.file);
reader.onload = (event) => {
fileWithImage.imageUrl = reader.result;
console.log(fileWithImage.file.name);
console.log(fileWithImage.imageUrl);
this.filesWithImages.push(fileWithImage);
};
}
}
component.html (selecting and displaying images):
<button
type="button"
mat-raised-button
(click)="fileInput.click()"
class="button"
>
Choose File
</button>
<input
hidden
(change)="onFilesSelected($event)"
#fileInput
type="file"
accept="image/*"
multiple="multiple"
/>
<div *ngFor="let file of filesWithImages" class="images">
<img
[src]="file.imageUrl"
height="10%"
width="10%"
*ngIf="file.imageUrl"
/>
</div>
I tried blocking the loop untill the reader.onload is executed with a use of a flag, but it did not work.
I also tried to get the url directly from a method:
createImageUrl(file: File): any {
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (event) => {
return reader.result;
};
}
and call it in [src] of an image tag in html, but it made my program crash.
The main problem is probably why the result of reader is null for the first few files and only the last one is properly displayed. Can someone help me to find the cause of this problem?
Try changing reader variable to local scope.
Change
var reader = new FileReader();
to
let reader = new FileReader();

how can i read with jquery a file csv that has been uploaded with html form?

I am trying to read a csv file with jquery. I have passed the file with input tag of html but i am having some problems to read it. Below the code that i have written.
HTML code:
<div id="insertCSV" class = "formblacktransparent">
<input id="csv" type="file" accept=".csv" class="form-control" placeholder="Insert csv"> </input>
<button type="button" class="log-btn" id="confCsv"> Confirm </button>
</div>
Jquery code:
$("#confCsv").click(function(data){
var input = document.getElementById('csv');
var file = input.files[0];
alert(file[0]);
var fr = new FileReader();
fr.readAsDataURL(data);
alert(fr);
});
I don 't understand if in this way the file has been uploaded and how i can accede to it.
Any ideas? thank you in advance!!
I write below the code that i have used to resolve my problem. I hope it can be useful. Hello!
document.querySelector("#confCsv").addEventListener('click', function() {
if(document.querySelector("#csv").files.length == 0) {
alert('Error : No file selected');
return;
}
// first file selected by user
var file = document.querySelector("#csv").files[0];
// perform validation on file type & size if required
// read the file
var reader = new FileReader();
// file reading started
reader.addEventListener('loadstart', function() {
console.log('File reading started');
});
// file reading finished successfully
reader.addEventListener('load', function(e) {
// contents of file in variable
var text = e.target.result;
var row = text.split('\n');
row.forEach(function(e) {
var datiGiornalieri = e.split(';');
socket.emit('parameterRegistrationFile', {ID: patientID, paramdata: datiGiornalieri[0], parametername: 'alfa',parametervalue: datiGiornalieri[1] });
});
});
reader.readAsText(file);
});

multiple FileUpload display file path as text [duplicate]

This question already has answers here:
How to get full path of selected file on change of <input type=‘file’> using javascript, jquery-ajax?
(14 answers)
Closed 6 years ago.
I have a select choice of files to upload can be single or multiple
as I select I would like to have a text below stated the path of the files I have selected.
<form action="mymethod" enctype="multipart/form-data" method="Post" id="submitForm">
<input id="file" name="file[]" multiple type="file">
Upon selecting the file let say its 3:
it will show on the screen:
however currently it is showing:
here is my script:
<script>
var selDiv = "";
document.addEventListener("DOMContentLoaded", init,
false);
function init() {
document.querySelector('#file').addEventListener(
'change', handleFileSelect, false);
selDiv = document.querySelector("#selectedFiles");
}
function handleFileSelect(e) {
if (!e.target.files)
return;
selDiv.innerHTML = "";
var files = e.target.files;
for ( var i = 0; i < files.length; i++) {
var f = files[i];
selDiv.innerHTML += f.name + "<br/>";
}
}
</script>
Prehaps you guys could give me suggestion on how I would tackle this issue?
You won't be able to access this via JavaScript; as a security precaution the browser will expose the file name to you, but nothing else about the local file system.
This is a built in security measure by the browser creators, so private information about local file paths cannot be seen.

How do I upload and process a file in Javascript?

I am creating a small html5 app that will allow users to change color properties of some elements. I want to give the user the option to save their changes and then upload them on later occasion (without registration). For this, I added a button that produces a text file of their properties, I want to add a button that will allow them to upload the file, I created a file picker dialog,
<label>
<input class="button"
type="file"
name="input-name"
style="display:none;"
onchange="read(event)"/>
<span id="input-file" >Select File</span>
</label>
But I can't figure how do I open this file in javascript and process its content. I know this should be similar to this
function read(evt){
var file = document.getElementById("input-file");
//checking for file reader
if (window.File && window.FileReader && window.FileList && window.Blob){
var r = new FileReader();
r.readAsText(file);
} else{
alert("Browser not supported");
}
}
But this doesn't work because file above is not the path to the file but the object. How do I get the path to the file? Is there a better way to do this?
You can read files via the File API, but you can't save them. You can create windows containing the text you want to save and then let the user save it, but it's a pain both when saving and loading.
Fortunately, for what you're talking about, you don't want files.
Instead, store the color preferences in web storage, specifically localStorage:
Loading (e.g., on page load or whenever):
var savedColor = localStorage.getItem("saved-color");
if (savedColor == null) {
// There wasn't one, use a default
}
Saving:
localStorage.setItem("saved-color", savedColor);
(localStorage in the above isn't a placeholder or anything; it's a global that's present on browsers that support local storage, which is [just about all of them2.)
Web storage values are always strings. You can use JSON if you need to store complex things.
Assuming your text file is in JSON (stringified format), i.e. your file.txt contains {"primary":"green","secondary":"#FF0000"}
<input type="file" id="file-picker" accept="text/plain" />
/*
Assuming JSON format in the text file - e.g:
var colors = {
primary: 'green',
secondary: '#FF0000'
}
JSON.stringify(colors);
output: '{"primary":"green","secondary":"#FF0000"}'
*/
var fileInput = document.querySelector('#file-picker');
function readFileJSON(file) {
return new Promise(function(resolve) {
var reader = new FileReader();
reader.onload = function(e) {
try {
resolve(JSON.parse(e.target.result));
} catch(ex) {
throw ex;
}
};
reader.readAsText(file);
});
}
fileInput.addEventListener('change', function(e) {
var file = e.target.files.item(0);
if (!file) {
return;
}
readFileJSON(file).then(function(colors) {
console.log('Colors:', colors);
});
});
JSBIN: https://jsbin.com/weriguhato/edit?html,js,output

Handling multiple files from an input element in an array with Google Apps Script

I have a form, which allows to select an item from a dropdown list and upload a file. The name and the ID of the item are saved in a Spreadsheet document. Works with one file...but I want to upload multiple files. Could you help me fixing the script?
The HTML part looks like this
<div class="col-md-4 col-sm-6 ">
<div class="caption">
<h3>Bildauswahl</h3>
<p align="center"><input type="file" name="myFiles[]" id="myFiles" multiple></p>
</div>
</div>
My script, which is not working, is the following:
var dropBoxId = "XYZ";
var logSheetId = "ABC";
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('InputForm.html');
}
function uploadFiles(formObject) {
try {
// Create a file in Drive from the one provided in the form
var folder = DriveApp.getFolderById(dropBoxId);
var input = document.getElementById('myFiles');
for (i = 0; i<input.files.length; i++) {
var blob = input.files[i];
var file = folder.createFile(blob);
var ss = SpreadsheetApp.openById(logSheetId);
var sheet = ss.getSheets()[0];
sheet.appendRow([file.getName(), file.getUrl(), formObject.myName]);
}
// Return the new file Drive URL so it can be put in the web app output
return file.getUrl();
} catch (error) {
return error.toString();
}
}
Thanks.
As of right now you have to use a work around to work with multiple files. The multiple attribute only works in IFRAME mode, but file inputs are broken in IFRAME mode.
To see this workaround take a look at the bug submission for this issue:
https://code.google.com/p/google-apps-script-issues/issues/detail?id=4610
Also in your code you have some mixing of server side and client side code that will not work:
var folder = DriveApp.getFolderById(dropBoxId); //server side
var input = document.getElementById('myFiles'); //client side
You will need to do your multiple file processing on the client side
I came up with a nice solution for multi-file uploading. Limitations are files must be under 10 MB.
CODE.GS
function doGet() {
return HtmlService.createHtmlOutputFromFile('index').setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function saveFile(data,name,folderId) {
var contentType = data.substring(5,data.indexOf(';'));
var file = Utilities.newBlob(Utilities.base64Decode(data.substr(data.indexOf('base64,')+7)), contentType, name);
DriveApp.getFolderById(folderId).createFile(file);
}
index.html
<div>
<input type="file" id="myFiles" name="myFiles" multiple/>
<input type="button" value="Submit" onclick="SaveFiles()" />
</div>
<script>
var reader = new FileReader();
var files;
var fileCounter = 0;
var folderId = "";
reader.onloadend = function () {
google.script.run
.withSuccessHandler(function(){
fileCounter++;
postNextFile();
}).saveFile(reader.result,files[fileCounter].name,folderId);
}
function SaveFiles(){
var folderSelect = document.getElementById("folderSelectId");
folderId = folderSelect.options[e.selectedIndex].value;
files = document.getElementById("myFiles").files;
postNextFile();
}
function postNextFile(){if(fileCounter < files.length){reader.readAsDataURL(files[fileCounter]);}else{fileCounter=0;alert("upload done")}}
</script>

Categories