I have two buttons - 'Input the File' which uploads a CSV file from PC and 'Load File' which loads it for other utility in my application.
<input type="file" class="custom-file-input form-control-sm" id="inputFile" onchange="handleFiles(this.files)" accept=".csv">
<label class="custom-file-label col-form-label-sm" for="inputFile" onclick="checkFunc()">Input the File</label>
<button type="button" class="btn btn-outline-dark rounded w1-right set-sql" id="lfb">Load File</button>
I want to add a js function to the Load File button so that when it loads file which is uploaded from the local PC, it checks the number of columns the file has and whether it is X number of columns. And then displays a success message(if X columns) or failure message(if more than or less than X number of columns).
Here is what I have tried. The function is not working. What can I do/change here?
async function checkFunc() {
if (inputFile.files.length) {
try {
var csvFileInText = await inputFile.files[0].text();
console.log(csvFileInText);
var arrObje = [];
var lines = csvFileInText.split('\n');
var lineA = lines[0].split(',');
let linesize = lineA.length;
if (linesize == 3){
alert("File uploaded successfully.");
}
else{
alert("File was not uploaded. Please check the instructions.");
}
} catch (e) {
console.error(e);
}
}
}
You need to split on the below characters that is why it isn't working for you:
let lines = csvFileInText.split(/\r?\n/);
Related
I have a problem while uploading files using a drop area. It seems that files get converted to strings when they arrive at the backend. I'm adding the file objects to a new array because I want the users to be able to remove unwanted files before they submit the form.
The form looks like this:
<form action="" class="dropzone" id="image_upload" enctype="multipart/form-data">
<div class="upload-input">
<label for="delivery_address" id="delivery_address_label">Delivery address</label>
<input type="text" name="delivery_address" id="delivery_address" class="form-control" />
</div>
<div class="" id="drop-area">
<p>Upload multiple files with the file dialog or by dragging and dropping images onto the dashed
region
</p>
</div>
<div class="upload-input">
<input class="btn btn-info w-100" type="submit" id="btnUpload" value="Send" />
</div>
</form>
Javascript:
let dropArea = document.getElementById("drop-area");
let fileList = [];
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, preventDefaults, false)
})
function preventDefaults(e) {
e.preventDefault()
e.stopPropagation()
}
dropArea.addEventListener('drop', handleDrop, false)
function handleDrop(e) {
let dt = e.dataTransfer;
let files = dt.files;
handleFiles(files);
}
function handleFiles(files) {
files = [...files];
files.forEach(addFiles);
}
function addFiles(file) {
fileList.push(file);
}
btnUpload.addEventListener("click", function(evt) {
evt.preventDefault();
const xhr = new XMLHttpRequest();
const form = document.getElementById("image_upload");
const formData = new FormData(form);
console.log(fileList);
formData.append("fileList", fileList);
xhr.open("POST", "add.php");
xhr.onreadystatechange = function() {
document.getElementById("phpResponse").innerHTML = this.responseText;
};
xhr.send(formData);
});
And in the PHP file I'm just var dumping $_FILES for now to see what's going through:
var_dump($_FILES);
Which returns
array(0) { }
var_dump($_POST) returns:
array(3) { ["delivery_type"]=> string(14) "Latvijas pasts" ["delivery_address"]=> string(6) "qweeqe" ["fileList"]=> string(27) "[object File],[object File]" }
I can't find where the problem is. The form is set to enctype="multipart/form-data". Before sending the form I console.log the fileList variable and it looks like the files are still files:
As suggested, I have to loop through every instance of File in the fileList array and append each File to FormData individually.
This part:
formData.append("fileList", fileList);;
Becomes:
for (let i = 0; i < fileList.length; i++) {
formData.append("fileList[]", fileList[i]);
}
And on the backend I can loop through every file:
foreach($_FILES['fileList']['tmp_name'] as $key => $tmp_name){
echo $_FILES['fileList']['name'][$key] . "<br />";
}
I have two buttons ... when clicked they display some text in a input field. I use some simple javascript to select which text to display, the one defined under the button with id="blabla1" or the one under the button with id="blabla2".
Is it possible to display the text defined in an external .txt file?
It is working fine with the text defined as value under the input button:
<input type="hidden" id="SupSite1Title" value="Subsite1 Title!"><br>
but i want text from a txt file instead.
<body>
<div id="leftnav">
<ul>
<li><input type="text" id="TextField1"><br><br></li>
</ul>
</div>
<div id="rightnav">
<ul>
<li><button id="blabla1" onclick="myFunction1()">Side1</button></li>
<li><button id="blabla2" onclick="myFunction2()">Side2</button></li>
</ul>
</div>
<input type="hidden" id="SupSite1Title" value="Subsite1 Title!"><br>
<input type="hidden" id="SupSite2Title" value="Subsite2 Title!"><br>
<script>
function myFunction1() {document.getElementById("TextField1").value =document.getElementById("SupSite1Title").value;
}
</script>
<script>
function myFunction2() {document.getElementById("TextField1").value =document.getElementById("SupSite2Title").value;
}
</script>
If you want to display the text content of the .txt file ... you can use an API called FileReader API (you need to check if your browser supports that)
here is how you can do it :
UPDATED :
var file1 = document.getElementById('file1');
var file2 = document.getElementById('file2');
document.getElementById('bOne').addEventListener("click", function(){getFile(file1)})
document.getElementById('bTwo').addEventListener("click", function(){getFile(file2)})
function getFile(target) {
const input = target;
if ('files' in input && input.files.length > 0) {
placeFileContent(
document.getElementById('display'),
input.files[0])
}
}
function placeFileContent(target, file) {
readFileContent(file).then(content => {
target.value = content
}).catch(error => console.log(error))
}
function readFileContent(file) {
const reader = new FileReader()
return new Promise((resolve, reject) => {
reader.onload = event => resolve(event.target.result)
reader.onerror = error => reject(error)
reader.readAsText(file)
})
}
label {
display : block;
margin-top : 40px;
margin-bottom : 20px;
}
<label for="file1">Upload file 1 : </label>
<input type="file" accept=".txt" id="file1" name="file1">
<label for="file2">Upload file 2 : </label>
<input type="file" accept=".txt" id="file2" name="file2">
<button id="bOne">Display file1</button>
<button id="bTwo">Display file2</button>
<label for="file2">Selected file : </label>
<input type="text" id="display" for="display">
METHOD N°2 (data fetching from a server) :
function fetchData(buttonNumber) {
var btn1 = document.getElementById('b1')
var btn2 = document.getElementById('b2')
var display = document.getElementById('display')
//fetching data
if (buttonNumber == 1) {
//replace 'file1.txt' with your file URL
fetch('file1.txt').then(x => {
x.text().then(function(text) {
display.value = text
});
})
} else {
//replace 'file2.txt' with your file URL
fetch('file2.txt').then(x => {
x.text().then(function(text) {
display.value = text
});
})
}
}
#b1,
#b2 {
display: block;
margin: 40px;
}
<button id="b1" onclick="fetchData(1)">Get file 1 and show it</button>
<button id="b2" onclick="fetchData(2)">Get file 2 and show it</button>
<label for="file2">Selected file : </label>
<input type="text" id="display" for="display">
If you want to read the contents of a text file you cannot load it from local file system. You should put it on server and load it from there.
Give the input field the attributes type="file" and accept=".txt", and that should work
<input type="file" accept=".txt" />
And you can read this .txt file using node.js(Also you can read it with vanilla js), But i prefer node.js like this
const fs = require('fs');
const fileData = fs.readFileSync('fileName.txt', 'utf-8');
console.log(fileData) // Whatever inside .txt file
Update according to comment:
Suppose in your project folder, you have one index.html file and one index.js file. Create two .txt file named as file1.txt and file2.txt And write something on those file. NOTE: For simplicity i am writing solution using jQuery.
index.html
<body>
<p id="text-field"></p>
<button id="btn1">Button 1</button>
<button id="btn2">Button 2</button>
</body>
index.js
const fs = require('fs');
let fileData = '';
$('#btn1').click(()=> {
fileData = fs.readFileSync('file1.txt', 'utf-8');
$('#text-field').append(fileData);
});
$('#btn2').click(()=> {
fileData = fs.readFileSync('file2.txt', 'utf-8');
$('#text-field').append(fileData);
});
That's it. According to button click text will be append into p element.
You can handle two button click with one function also, like this
$('button').click(event => {
event.stopImmediatePropagation();
event.stopPropagation();
if($(event.target).attr('id') === 'btn1') {
fileData = fs.readFileSync('file1.txt', 'utf-8');
$('#text-field').append(fileData);
}else if($(event.target).attr('id') === 'btn2') {
fileData = fs.readFileSync('file2.txt', 'utf-8');
$('#text-field').append(fileData);
}
});
I want to allow the user to upload only pdf files in two input files:
<form onsubmit='return checkExt()' action='upload.php' method='POST'>
<label>upload the first file</label>
<input type='file' name='fileToUpload' id='fileToUpload' required>
<label>upload the secondfile</label>
<input type='file' name='fileToUpload1' id='fileToUpload1' required>
</form>
I used the following script to check the extension of the files-to-upload:
<script>
function checkExt() {
var allowedFiles = [".pdf"];
var form_valid = document.getElementById("fileToUpload");
var form_valid2 = document.getElementById("fileToUpload1");
var regex = new RegExp("([a-zA-Z0-9\s_\\.\-:])+(" + allowedFiles.join('|') + ")$");
if (!regex.test((form_valid.value.toLowerCase()) &&(form_valid2.value.toLowerCase()))) {
alert('only PDF files are allowed');
return false;
}
return true;
}
</script>
the problem is: when I test it, it only checks on the first file if it is a pdf or not. it does not check on the second file.
You don't need javascript to validate the filetypes. Just use to accept attribute in the input tag.
See documentation here: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
<input name="myFile" type="file" accept=".pdf" multiple>
Your second check in the if condition should mirror the first one and this is the reason why it doesn't work.
Anyway the easiest and scalable way is to iterate over input fields of type "file". Like this:
function checkExt() {
var fileInputs = document.querySelectorAll('input[type="file"]');
var isValid = true;
var allowedFiles = [".pdf"];
var regex = new RegExp(
"([a-zA-Z0-9s_\\.-:])+(" + allowedFiles.join("|") + ")$"
);
fileInputs.forEach(function(input) {
if (!regex.test(input.value.toLowerCase())) {
isValid = false;
}
});
if (isValid) {
alert("only PDF files are allowed");
}
return isValid;
}
This allows you to add as many file input fields as you want.
I'm trying to create an AngularJS form. One part of the form is taking the Base64 from a file and storing it to my $scope.user. However, clicking a file upload input and selecting my file is submitting my form, which should not be happening.
Here's my form:
<form ng-submit="processForm()" name="merchApp" style="position:relative">
<div class="form-section" ui-view>
<div class="row">
<div class="col-sm-12 text-center">
<button href="#" ng-click='docUpload("userId")'>Upload File</button> {{user.uploadIdName}}
<br/>* Accepted file types: .jpg, .png, .gif, .pdf, .doc, .docx
<br/>
(Max file size: 2MB)
<br/>
<input ng-model="user.uploadId" type="hidden" value="{{user.uploadId}}" required>
<br/><br/>
<button type="submit" class="next" ng-disabled="merchApp.$invalid">SUBMIT APPLICATION</button>
</div>
</div>
</div>
</form>
Here's my app.js
.controller('formController', ['$scope', '$http', '$parse', function($scope, $http, $parse) {
// we will store all of our form data in this object
$scope.user = {};
$scope.docUpload = function() { //default function, to be override if browser supports input type='file'
$scope.data.alert = "Your browser doesn't support HTML5 input type='File'"
}
var fileUploadScope;
var fileSelect = document.createElement('input'); //input it's not displayed in html, I want to trigger it form other elements
fileSelect.type = 'file';
if (fileSelect.disabled) { //check if browser support input type='file' and stop execution of controller
return;
}
var fileUploadScope;
var fileUploadName;
$scope.docUpload = function(x) { //activate function to begin input file on click
switch(x){
case "checkBankLetter":
fileUploadScope = $parse("uploadCheckBankLetter");
fileUploadName = $parse("uploadCheckBankLetterFileName");
break;
case "userId":
fileUploadScope = $parse("uploadId");
fileUploadName = $parse("uploadIdName");
break;
default:
alert ("error");
}
fileSelect.click();
}
fileSelect.onchange = function() { //set callback to action after choosing file
var f = fileSelect.files[0];
var fsize = f.size;
var fileTypes = ['jpg', 'jpeg', 'png', 'doc', 'docx', 'pdf', 'gif'];
if (fsize > 2097152){//file size limit is 2MB
alert ("File size too large. Please select a file 2MB or smaller.");
}
else {// file size is acceptable
if(f){
var extension = f.name.split('.').pop().toLowerCase(), //file extension from input file
isSuccess = fileTypes.indexOf(extension) > -1; //is extension in acceptable types
if (isSuccess) { //yes
var r = new FileReader();
r.fileName = f.name;
if (typeof FileReader !== "undefined"){
r.onloadend = function(e) { //callback after files finish loading
// allow for different scope names for file upload functions
fileUploadScope.assign($scope.user, e.target.result);
fileUploadName.assign($scope.user, r.fileName);
$scope.$apply();
//here you can send data over your server as desired
}
r.readAsDataURL(f); //once defined all callbacks, begin reading the file
}
}
else {
alert("Please select an acceptable file type");
}
}
}
};
// function to process the form
$scope.processForm = function() {
$http({
method : 'POST',
url : 'docusign.php',
data : $scope.user // pass in data as strings
})
.success(function(data) {
console.log(data);
location.replace(data);
});
};
}])
processForm() is firing after I click <button href="#" ng-click='docUpload("userId")'>Upload File</button> and select a file, and I can't figure out why this is happening.
Ideally it is better practice to specify type attribute for buttons.
button without type attribute acts as submit buttons that is reason your form getting submitted when you click on button.
So add type attribute to button.| type="button"
remove href attribute since it is unnecessary for button.
Change this line
<button href="#" ng-click='docUpload("userId")'>Upload File</button>
to
<button type="button" ng-click='docUpload("userId")'>Upload File</button>
I'm not sure if this is best practices, but I was able to fix my problem by adding onclick="return false" to my input button.
How can I validate if the user has selected a file to upload?
Edit: bumped
Check it's value property:
In jQuery (since your tag mentions it):
$('#fileInput').val()
Or in vanilla JavaScript:
document.getElementById('myFileInput').value
My function will check if the user has selected the file or not and you can also check whether you want to allow that file extension or not.
Try this:
<input type="file" name="fileUpload" onchange="validate_fileupload(this.value);">
function validate_fileupload(fileName)
{
var allowed_extensions = new Array("jpg","png","gif");
var file_extension = fileName.split('.').pop().toLowerCase(); // split function will split the filename by dot(.), and pop function will pop the last element from the array which will give you the extension as well. If there will be no extension then it will return the filename.
for(var i = 0; i <= allowed_extensions.length; i++)
{
if(allowed_extensions[i]==file_extension)
{
return true; // valid file extension
}
}
return false;
}
Building on Ravinders solution, this code stops the form being submitted. It might be wise to check the extension at the server-side too. So you don't get hackers uploading anything they want.
<script>
var valid = false;
function validate_fileupload(input_element)
{
var el = document.getElementById("feedback");
var fileName = input_element.value;
var allowed_extensions = new Array("jpg","png","gif");
var file_extension = fileName.split('.').pop();
for(var i = 0; i < allowed_extensions.length; i++)
{
if(allowed_extensions[i]==file_extension)
{
valid = true; // valid file extension
el.innerHTML = "";
return;
}
}
el.innerHTML="Invalid file";
valid = false;
}
function valid_form()
{
return valid;
}
</script>
<div id="feedback" style="color: red;"></div>
<form method="post" action="/image" enctype="multipart/form-data">
<input type="file" name="fileName" accept=".jpg,.png,.bmp" onchange="validate_fileupload(this);"/>
<input id="uploadsubmit" type="submit" value="UPLOAD IMAGE" onclick="return valid_form();"/>
</form>
In Firefox at least, the DOM inspector is telling me that the File input elements have a property called files. You should be able to check its length.
document.getElementById('myFileInput').files.length
I got this from some forum. I hope it will be useful for you.
<script type="text/javascript">
function validateFileExtension(fld) {
if(!/(\.bmp|\.gif|\.jpg|\.jpeg)$/i.test(fld.value)) {
alert("Invalid image file type.");
fld.form.reset();
fld.focus();
return false;
}
return true;
} </script> </head>
<body> <form ...etc... onsubmit="return
validateFileExtension(this.fileField)"> <p> <input type="file"
name="fileField" onchange="return validateFileExtension(this)">
<input type="submit" value="Submit"> </p> </form> </body>
Simple and powerful way(dynamic validation)
place formats in array like "image/*"
var upload=document.getElementById("upload");
var array=["video/mp4","image/png"];
upload.accept=array;
upload.addEventListener("change",()=>{
console.log(upload.value)
})
<input type="file" id="upload" >