Dropzone Js get file data (csv. xlsx) before Uploading - javascript

I'm new to Dropzone Js and i want to upload a file, process data to json then upload to my Flask server.
i appreciate any kind of help, thanks.
var id = '#kt_dropzone_4';
// set the preview element template
var previewNode = $(id + " .dropzone-item");
previewNode.id = "";
var previewTemplate = previewNode.parent('.dropzone-items').html();
previewNode.remove();
var myDropzone4 = new Dropzone(id, { // Make the whole body a dropzone
url: "/Upload", // Set the url for your upload script location
headers: {
'x-csrftoken': $('#csrf_Upload').val()
},
method: "post",
parallelUploads: 5,
acceptedFiles: ".xls, .xlsx, .csv",
previewTemplate: previewTemplate,
maxFilesize: 2, // Max filesize in MB
autoQueue: false, // Make sure the files aren't queued until manually added
previewsContainer: id + " .dropzone-items", // Define the container to display the previews
clickable: id +
" .dropzone-select" // Define the element that should be used as click trigger to select files.
});
myDropzone4.on("addedfile", function (file) {
// Hookup the start button
file.previewElement.querySelector(id + " .dropzone-start").onclick = function () {
myDropzone4.enqueueFile(file);
};
$(document).find(id + ' .dropzone-item').css('display', '');
$(id + " .dropzone-upload, " + id + " .dropzone-remove-all").css('display', 'inline-block');
//remove duplicates
if (this.files.length) {
var i, len;
for (i = 0, len = this.files.length; i < len - 1; i++) // -1 to exclude current file
{
if (this.files[i].name === file.name && this.files[i].size === file.size && this.files[i]
.lastModifiedDate.toString() === file.lastModifiedDate.toString()) {
this.removeFile(file);
$('#muted-span').text('Duplicates are not allowed').attr('class', 'kt-font-danger kt-font-bold').hide()
.fadeIn(1000)
setTimeout(function () {
$('#muted-span').hide().text('Only Excel and csv files are allowed for upload')
.removeClass('kt-font-danger kt-font-bold').fadeIn(500);
}, 2500);
}
}
}
});
// Update the total progress bar
myDropzone4.on("totaluploadprogress", function (progress) {
$(this).find(id + " .progress-bar").css('width', progress + "%");
});
myDropzone4.on("sending", function (file, response) {
console.log(file)
console.log(response)
// Show the total progress bar when upload starts
$(id + " .progress-bar").css('opacity', '1');
// And disable the start button
file.previewElement.querySelector(id + " .dropzone-start").setAttribute("disabled", "disabled");
});
// Hide the total progress bar when nothing's uploading anymore
myDropzone4.on("complete", function (progress) {
var thisProgressBar = id + " .dz-complete";
setTimeout(function () {
$(thisProgressBar + " .progress-bar, " + thisProgressBar + " .progress, " + thisProgressBar +
" .dropzone-start").css('opacity', '0');
}, 300)
});
// Setup the buttons for all transfers
document.querySelector(id + " .dropzone-upload").onclick = function () {
myDropzone4.enqueueFiles(myDropzone4.getFilesWithStatus(Dropzone.ADDED));
};
// Setup the button for remove all files
document.querySelector(id + " .dropzone-remove-all").onclick = function () {
$(id + " .dropzone-upload, " + id + " .dropzone-remove-all").css('display', 'none');
myDropzone4.removeAllFiles(true);
};
// On all files completed upload
myDropzone4.on("queuecomplete", function (progress) {
$(id + " .dropzone-upload").css('display', 'none');
});
// On all files removed
myDropzone4.on("removedfile", function (file) {
if (myDropzone4.files.length < 1) {
$(id + " .dropzone-upload, " + id + " .dropzone-remove-all").css('display', 'none');
}
});
I have not found yet a way to get the uploaded data from dropzonejs. I tried to read the file with FileReader but it's not a binary data (correct me if i'm wrong).
I need to process data on myDropzone4.on("addedfile", function (file){})
and return it as a json format if possible.

I found an answer for it, I just needed to find the input type file.when using dropzone.js either you find the input type file in the html page or in their javascript file, where i found that the input type file was being created with a class to hide this element :
var setupHiddenFileInput = function setupHiddenFileInput() {
if (_this3.hiddenFileInput) {
_this3.hiddenFileInput.parentNode.removeChild(_this3.hiddenFileInput);
}
_this3.hiddenFileInput = document.createElement("input");
_this3.hiddenFileInput.setAttribute("type", "file");
_this3.hiddenFileInput.setAttribute("id", "123");
if (_this3.options.maxFiles === null || _this3.options.maxFiles > 1) {
_this3.hiddenFileInput.setAttribute("multiple", "multiple");
}
// _this3.hiddenFileInput.className = "dz-hidden-input";
}
so i gave it an id and bind an event to the input then i read the file with two functions depends on the format of the file uploaded, for csv files to json :
function getText(fileToRead) {
var reader = new FileReader();
reader.readAsText(fileToRead);
reader.onload = loadHandler;
reader.onerror = errorHandler;
}
function loadHandler(event) {
var csv = event.target.result;
process(csv);
}
function process(csv) {
// Newline split
var lines = csv.split("\n");
result = [];
var headers = lines[0].split(",");
for (var i = 1; i < lines.length - 1; i++) {
var obj = {};
//Comma split
var currentline = lines[i].split(",");
for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
console.log(result);
}
function errorHandler(evt) {
if (evt.target.error.name == "NotReadableError") {
alert("Canno't read file !");
}
}
Read excel files (xls,xlsx) format to json format:
var ExcelToJSON = function () {
this.parseExcel = function (file) {
var reader = new FileReader();
reader.onload = function (e) {
var data = e.target.result;
var workbook = XLSX.read(data, {
type: 'binary'
});
workbook.SheetNames.forEach(function (sheetName) {
// Here is your object
var XL_row_object = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[
sheetName]);
var json_object = JSON.stringify(XL_row_object);
console.log(JSON.parse(json_object));
jQuery('#xlx_json').val(json_object);
})
};
reader.onerror = function (ex) {
console.log(ex);
};
reader.readAsBinaryString(file);
};
};
the event that will detect change on the input, detect file format then use one of those to get the result in a JSON format:
$(document).ready(function () {
$('input[type="file"]').on('change', function (e) {
// EXCEL TO JSON
var files = e.target.files;
console.log(files)
var xl2json = new ExcelToJSON();
xl2json.parseExcel(files[0]);
var fileName = e.target.files[0].name;
console.log('The file "' + fileName + '" has been selected.');
// CSV TO JSON
var files = e.target.files;
if (window.FileReader) {
getText(files[0]);
} else {
alert('FileReader are not supported in this browser.');
}
});
});
I hope this helps i'm using dropzonejs with keenthemes implementation.

Related

count number entry in a CSV file using javascript in mvc

I am trying to check the file extension and count number of entry in the CSV file. At the moment the file extension check worked. My problem is the count of number row in the CSV at the moment when i run the code the count is 1 but the file selected has more than one entry. Any help please
HTML
<input type="file" name="attachmentcsv" onchange="ValidateSingleInput(this);" class="form-control" id="attachmentcsv" />
JavaScript
var _validFileExtensions = [".csv", ".CSV"];
function ValidateSingleInput(oInput) {
if (oInput.type == "file") {
var sFileName = oInput.value;
var lines = sFileName.split('\r').length;
// Check if the CSV file is valid and count the number of entry
if (sFileName.length > 0) {
var blnValid = false;
for (var j = 0; j < _validFileExtensions.length; j++) {
var sCurExtension = _validFileExtensions[j];
if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length).toLowerCase() == sCurExtension.toLowerCase()) {
// show row count in the CVS file. Error is here
alert("CVS file has " + lines + " Numbers");
blnValid = true;
break;
}
}
if (!blnValid) {
alert("Sorry the file, " + sFileName + " selected is invalid, file extensions allowed are: " + _validFileExtensions.join(" , "));
oInput.value = "";
return false;
}
}
}
return true;
}
code below works for me
document.getElementById('attachmentcsv').addEventListener('change', readSingleFile, false);
function readSingleFile(evt) {
//Retrieve the first (and only!) File from the FileList object
var f = evt.target.files[0];
if (f) {
var r = new FileReader();
r.onload = function (e) {
var contents = e.target.result;
var lines = contents.split("\n").length;
// Remove header count
var mobileEntryCount= lines -1
if (mobileEntryCount <= 1) {
$('#csvcount').css('display', 'block');
$('#csvcount').text('CSV File Selected has ' + mobileEntryCount + ' Mobile Number Saved');
} else {
$('#csvcount').css('display', 'block');
$('#csvcount').text('CSV File Selected has ' + mobileEntryCount + ' Mobiles Number Saved');
}
}
r.readAsText(f);
} else {
alert("Failed to load file");
}
}

Javascript Drag and Drop Files, then Sort

I am trying to Sort files I pull from File Explorer by name, they sort by when they load, how would I sort them by name instead using my code below?
(function() {
// getElementById
function $id(id) {
return document.getElementById(id);
}
// output information
function Output(msg) {
var m = $id("messages");
m.innerHTML = msg + m.innerHTML;
}
// file drag hover
function FileDragHover(e) {
e.stopPropagation();
e.preventDefault();
e.target.className = (e.type == "dragover" ? "hover" : "");
}
// file selection
function FileSelectHandler(e) {
// cancel event and hover styling
FileDragHover(e);
// fetch FileList object
var files = e.target.files || e.dataTransfer.files;
// process all File objects
for (var i = 0, f; f = files[i]; i++) {
ParseFile(f);
}
}
// output file information
function ParseFile(file) {
// display an image
if (file.type.indexOf("image") == 0) {
var reader = new FileReader();
reader.onload = function(e) {
Output(
"<p align=center><strong>" + file.name + ":</strong><br />" +
'<img src="' + e.target.result + '"></p>'
);
}
reader.readAsDataURL(file);
}
// display text
if (file.type.indexOf("text") == 0) {
var reader = new FileReader();
reader.onload = function(e) {
Output(
"<p><strong>" + file.name + ":</strong></p><pre>" +
e.target.result.replace(/</g, "<").replace(/>/g, ">") +
"</pre>"
);
}
reader.readAsText(file);
}
}
// initialize
function Init() {
var fileselect = $id("fileselect"),
filedrag = $id("filedrag"),
submitbutton = $id("submitbutton");
// file select
fileselect.addEventListener("change", FileSelectHandler, false);
// is XHR2 available?
var xhr = new XMLHttpRequest();
if (xhr.upload) {
// file drop
filedrag.addEventListener("dragover", FileDragHover, false);
filedrag.addEventListener("dragleave", FileDragHover, false);
filedrag.addEventListener("drop", FileSelectHandler, false);
filedrag.style.display = "block";
// remove submit button
submitbutton.style.display = "none";
}
}
// call initialization file
if (window.File && window.FileList && window.FileReader) {
Init();
}
})();
This code drags and drops the Files in my program and loads them, but does not sort in alphabetical, what would be the best way to sort them with my code below?
var files;
(function() {
// getElementById
function $id(id) {
return document.getElementById(id);
}
// output information
function Output(msg) {
var m = $id("messages");
m.innerHTML = msg + m.innerHTML;
}
// file drag hover
function FileDragHover(e) {
e.stopPropagation();
e.preventDefault();
e.target.className = (e.type == "dragover" ? "hover" : "");
}
// file selection
function FileSelectHandler(e) {
// cancel event and hover styling
FileDragHover(e);
// fetch FileList object
var files = e.target.files || e.dataTransfer.files;
// process all File objects
for (var i = 0, f; f = files[i]; i++) {
ParseFile(f);
}
}
// output file information
function ParseFile(file) {
// display an image
var basename = file.name.substring(0,file.name.length-4);
files.push("<div style=\"width: 100%; overflow: hidden;\"><div style=\"width: 600px; float: left;\">" +
"<strong>" + basename + ".pdf:</strong><br />" +
'<iframe src="\\\\sovarchpri01\\d$\\1000Sunrise\\Process\\stage\\' + basename +".pdf#view=fit" + '"height="75%" width="500px"></iframe></p>' +
"</div><div style=\"margin-left: 620px;\">" +
"<strong>" + basename + ".png:</strong><br />" +
"<img src=\"\\\\sovarchpri01\\d$\\Fleissner\\ORG_5535_Documents\\" + basename + ".png\" height=\"75%\" width=\"500px\">" +
"</div> ");
}
function sortFiles() {
files.sort().reverse();
for (var i = 0; i < files.length; ++i) {
Output(files[i]);
}
}
function resetWindow(){
window.location.reload(true)
}
// initialize
function Init() {
var fileselect = $id("fileselect"),
filedrag = $id("filedrag"),
submitbutton = $id("submitbutton"),
sortbutton = $id("sortbutton"),
resetbutton = $id("resetbutton")
resetbutton2 = $id("resetbutton2");;
files = new Array();
// file select
fileselect.addEventListener("change", FileSelectHandler, false);
// is XHR2 available?
var xhr = new XMLHttpRequest();
if (xhr.upload) {
// file drop
filedrag.addEventListener("dragover", FileDragHover, false);
filedrag.addEventListener("dragleave", FileDragHover, false);
filedrag.addEventListener("drop", FileSelectHandler, false);
filedrag.style.display = "block";
// remove submit button
submitbutton.addEventListener("click", sortFiles , false); //style.display = "none";
sortbutton.addEventListener("click", sortFiles , false);
resetbutton.addEventListener("click", resetWindow , false);
resetbutton2.addEventListener("click", resetWindow , false);
}
}
// call initialization file
if (window.FileReader) {
Init();
}
})();

Get Byte Position during Upload Loop

I am working on a function that will write data to a remote server in chunks using a 3rd party API. Through some help on Stack Overflow I was able to accomplish this, where it is now working as expected. The problem is that I can only get a single 16kb chunk to write as I will need to advance the pos of where the next bytes are written to.
The initial write starts at 0 easily enough. Due to my unfamiliarity with this though, I am unsure if the next pos should just be 16 or what. If it helps, the API call writeFileChunk() takes 3 parameters, filepath (str), pos (int64), and data (base64 encoded string).
reader.onload = function(evt)
{
// Get SERVER_ID from URL
var server_id = getUrlParameter('id');
$("#upload_status").text('Uploading File...');
$("#upload_progress").progressbar('value', 0);
var chunkSize = 16<<10;
var buffer = evt.target.result;
var fileSize = buffer.byteLength;
var segments = Math.ceil(fileSize / chunkSize); // How many segments do we need to divide into for upload
var count = 0;
// start the file upload
(function upload()
{
var segSize = Math.min(chunkSize, fileSize - count * chunkSize);
if (segSize > 0)
{
$("#upload_progress").progressbar('value', (count / segments));
var chunk = new Uint8Array(buffer, count++ * chunkSize, segSize); // get a chunk
var chunkEncoded = btoa(String.fromCharCode.apply(null, chunk));
// Send Chunk data to server
$.ajax({
type: "POST",
url: "filemanagerHandler.php",
data: { 'action': 'writeFileChunk', 'server_id': server_id, 'filepath': filepath, 'pos': 0, 'chunk': chunkEncoded },
dataType: 'json',
success: function(data)
{
console.log(data);
setTimeout(upload, 100);
},
error: function(XMLHttpRequest, textStatus, errorThrown)
{
alert("Status: " + textStatus); alert("Error: " + errorThrown); alert("Message: " + XMLHttpRequest.responseText);
}
});
}
else
{
$("#upload_status").text('Finished!');
$("#upload_progress").progressbar('value', 100);
getDirectoryListing(curDirectory);
}
})()
};
The current position for the file on client side would be represented by this line, or more specifically the second argument at the pre-incremental step:
var chunk = new Uint8Array(buffer, count++ * chunkSize, segSize);
though, in this case it advances (count++) before you can reuse it so if you need the actual position (below as pos) you can extract it by simply rewriting the line into:
var pos = count++ * chunkSize; // here chunkSize = 16kb
var chunk = new Uint8Array(buffer, pos, segSize);
Here each position update will increment 16kb as that is the chunk-size. For progress then it is calculated pos / fileSize * 100. This of course assuming using the unencoded buffer size.
The only special case is the last chunk, but when there are no more chunks left to read the position should be equal to the file length (fileSize) so it should be pretty straight-forward.
When the ajax call return the server should have the same position unless something went wrong (connection, write access change, disk full etc.).
You can use Filereader API to read the chunks and send it to your remote server.
HTML
<input type="file" id="files" name="file" /> Read bytes:
<span class="readBytesButtons">
<button>Read entire file in chuncks</button>
</span>
Javascript
// Post data to your server.
function postChunk(obj) {
var url = "https://your.remote.server";
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('post', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
var status = xhr.status;
if (status == 200) {
resolve(xhr.response);
} else {
reject(status);
}
};
var params = "";
// check that obj has the proper keys and create the url parameters
if (obj.hasOwnProperty(action) && obj.hasOwnProperty(server_id) && obj.hasOwnProperty(filepath) && obj.hasOwnProperty(pos) && obj.hasOwnProperty(chunk)) {
params += "action="+obj[action]+"&server_id="+obj[server_id]+"&filepath="+obj[filepath]+"&pos="+obj[pos]+"&chunk="+obj[chunk];
}
if(params.length>0) {
xhr.send(params);
} else {
alert('Error');
}
});
}
// add chunk to "obj" object and post it to server
function addChunk(reader,obj,divID) {
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
obj.chunk = evt.target.result;
console.log(obj);
document.getElementById(divID).textContent +=
['Sending bytes: ', obj.pos*16000, ' - ', ((obj.pos*16000)+(obj.pos+1)*obj.chunk.length),
'\n'].join('');
// post data to server
postChunk(obj).then(function(data) {
if(data!=="" && data!==null && typeof data!=="undefined") {
// chunk was sent successfully
document.getElementById(divID).textContent +=
['Sent bytes: ', obj.pos*16000, ' - ', ((obj.pos*16000)+(obj.pos+1)*obj.chunk.length),'\n'].join('');
} else {
alert('Error! Empty response');
}
}, function(status) {
alert('Resolve Error');
});
}
};
}
// read and send Chunk
function readChunk() {
var files = document.getElementById('files').files;
if (!files.length) {
alert('Please select a file!');
return;
}
var file = files[0];
var size = parseInt(file.size);
var chunkSize = 16000;
var chunks = Math.ceil(size/chunkSize);
var start,stop = 0;
var blob = [];
for(i=0;i<chunks;i++) {
start = i*chunkSize;
stop = (i+1)*chunkSize-1;
if(i==(chunks-1)) {
stop = size;
}
var reader = new FileReader();
blob = file.slice(start, stop);
reader.readAsBinaryString(blob);
var obj = {action: 'writeFileChunk', server_id: 'sid', filepath: 'path', pos: i, chunk: ""};
var div = document.createElement('div');
div.id = "bytes"+i;
document.body.appendChild(div);
addChunk(reader,obj,div.id);
}
}
// Check for the various File API support.
if (window.File && window.FileReader && window.FileList && window.Blob) {
console.log(' Great success! All the File APIs are supported.');
} else {
alert('The File APIs are not fully supported in this browser.');
}
document.querySelector('.readBytesButtons').addEventListener('click', function(evt) {
if (evt.target.tagName.toLowerCase() == 'button') {
readChunk();
}
}, false);
You can check this example in this Fiddle

Allow only images in file upload form element in directory HTML5

HTML Code
<input type="file" accept="image/*" multiple webkitdirectory mozdirectory msdirectory odirectory directory id="fileURL"/>
Javascript Code:
var files,
file,
extension,
sum,
input = document.getElementById("fileURL"),
output = document.getElementById("fileOutput"),
holder = document.getElementById("fileHolder")
sizeShow = document.getElementById("filesSize");
input.addEventListener("change", function (e) {
files = e.target.files;
output.innerHTML = "";
sum = 0;
for (var i = 0, len = files.length; i < len; i++) {
file = files[i];
extension = file.name.split(".").pop();
if(extension=="jpg"||extension=="png"){
var size = Math.floor(file.size/1024 * 100)/100;
sum = size+sum;
output.innerHTML += "<li class='type-" + extension + "'>"+file.webkitRelativePath + file.name + " (" + size + "KB)</li>";
}else{
file.remove();
}
}
if(sum<1024*1024){
sizeShow.innerHTML = Math.floor(sum/1024*100)/100 + " MB";
}else if(sum>1024*1024){
sizeShow.innerHTML = Math.floor(sum/1024*1024*100)/100 + " GB";
}
}, false);
How do i get just the image in the file upload? accept="image/*" doesn't work for directory.
This does work but the statement file.remove() doesn't work at all.
I guess the input:file is read-only.
How do i solve this?
You can set input.files to a FileList (obtained from e.g. drag and drop), but you cannot create/modify a FileList. So you cannot modify the files of an input to e.g. only contain images.
What you can do, though, is uploading manually (through ajax), and only send files that have a type starting with "image/". See http://jsfiddle.net/WM6Sh/1/.
$("form").on("submit", function(e) {
e.preventDefault();
var files = $(this).find("input").prop("files");
var images = $.grep(files, function(file) {
return file.type.indexOf("image/") === 0; // filter out images
});
var xhr = new XMLHttpRequest();
xhr.open("POST", "/", true);
$(xhr).on("readystatechange", function(e) {
if(xhr.readyState === 4) {
console.log("Done");
}
});
var data = new FormData();
$.each(images, function(i) {
data.append(i, this); // append each image file to the data to be sent
});
console.log(
"Sending %d images instead of all %d files...",
images.length,
files.length
);
xhr.send(data);
});

File data from input element

In Firefox 3 it is possible to access the contents of a <input type="file"> element as in the following.
Assume a form with the following element:
<input type="file" id="myinput">
Now the data of the file selected can be accessed with:
// Get the file's data as a data: URL
document.getElementById('myinput').files[0].getAsDataURL()
Is there a cross-browser way to accomplish the same thing?
Firefox documentation for this feature:
https://developer.mozilla.org/en/nsIDOMFileList
https://developer.mozilla.org/en/nsIDOMFile
This is possible in at least Chrome, Firefox and Safari: Reading Files.
see associated jsfiddle
function readBlob(opt_startByte, opt_stopByte) {
var files = document.getElementById('files').files;
if (!files.length) {
alert('Please select a file!');
return;
}
var file = files[0];
var start = parseInt(opt_startByte) || 0;
var stop = parseInt(opt_stopByte) || file.size - 1;
var reader = new FileReader();
// If we use onloadend, we need to check the readyState.
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
document.getElementById('byte_content').textContent = _.reduce(evt.target.result,
function(sum, byte) {
return sum + ' 0x' + String(byte).charCodeAt(0).toString(16);
}, '');
document.getElementById('byte_range').textContent =
['Read bytes: ', start + 1, ' - ', stop + 1,
' of ', file.size, ' byte file'].join('');
}
};
var blob;
if (file.slice) {
blob = file.slice(start, stop + 1);
}else if (file.webkitSlice) {
blob = file.webkitSlice(start, stop + 1);
} else if (file.mozSlice) {
blob = file.mozSlice(start, stop + 1);
}
console.log('reader: ', reader);
reader.readAsBinaryString(blob);
}
document.querySelector('.readBytesButtons').addEventListener('click', function(evt) {
if (evt.target.tagName.toLowerCase() == 'button') {
var startByte = evt.target.getAttribute('data-startbyte');
var endByte = evt.target.getAttribute('data-endbyte');
readBlob(startByte, endByte);
}
}, false);

Categories