How to remove one specific selected file from input file control - javascript

How to remove one specific selected file from input file control?
I have an input file control with the option to select multiple files; however, I want to validate a file and if it has an wrong extension then I should remove that file from the file control itself, is it possible?
I tried as below
<input type="file" name="fileToUpload" id="fileToUpload" multiple/>
<script> $("#fileToUpload")[0].files[0] </script>
Below is the screenshot of the object but I am not able to modify it

As other people pointed out, FileList is read only. You can get around this by pushing those files into a separate Array though. You can then do whatever you want with that curated list of files. If uploading them to a server is the goal, you can use the FileReader API.
Below is a round about way of completely avoiding needing to modify the FileList.
Steps:
Add normal file input change event listener
Loop through each file from change event, filter for desired validation
Push valid files into separate array
Use FileReader API to read files locally
Submit valid, processed files to server
Event handler and basic file loop code:
var validatedFiles = [];
$("#fileToUpload").on("change", function (event) {
var files = event.originalEvent.target.files;
files.forEach(function (file) {
if (file.name.matches(/something.txt/)) {
validatedFiles.push(file); // Simplest case
} else {
/* do something else */
}
});
});
Below is a more complicated version of the file loop that shows how you can use the FileReader API to load the file into the browser and optionally submit it to a server as a Base64 encoded blob.
files.forEach(function (file) {
if (file.name.matches(/something.txt/)) { // You could also do more complicated validation after processing the file client side
var reader = new FileReader();
// Setup listener
reader.onload = (function (processedFile) {
return function (e) {
var fileData = { name : processedFile.name, fileData : e.target.result };
// Submit individual file to server
$.post("/your/url/here", fileData);
// or add to list to submit as group later
validatedFiles.push(fileData);
};
})(file);
// Process file
reader.readAsDataURL(file);
} else {
/* still do something else */
}
});
A note of caution about using FileReader API. Base64 encoding a file will increase its size by around 30%. If that isn't acceptable you will need to try something else.

I know this is an old post but I have spent ages trying to work around this one so I'll post my solution. There is a way to update the fileList of an fileField element with another fileList - which can be done with DataTransfer:
let updateFileList = function (fileField, index) {
let fileBuffer = Array.from(fileField.files);
fileBuffer.splice(index, 1);
/** Code from: https://stackoverflow.com/a/47172409/8145428 */
const dT = new ClipboardEvent('').clipboardData || // Firefox < 62 workaround exploiting https://bugzilla.mozilla.org/show_bug.cgi?id=1422655
new DataTransfer(); // specs compliant (as of March 2018 only Chrome)
for (let file of fileBuffer) { dT.items.add(file); }
fileField.files = dT.files;
}
The above function takes the fileField as a DOM Object and the index of the file in the fileField's fileList to be removed and updates the passed fileField accordingly.
Hope this saves somebody else some time!
How to set File objects and length property at FileList object where the files are also reflected at FormData object?

I thought that I should add my comment here as well here (I've answered here: JavaScript delete File from FileList to be uploaded)
I found a workaround. This will not require AJAX for the request at all and the form can be sent to the server. Basically you could create an hidden or text input and set it's value attribute to the base64 string created after processing the file selected.
<input type=hidden value=${base64string} />
You will probably consider the idea to create multiple input file instead of input text or hidden. This will not work as we can't assign a value to it.
This method will include the input file in the data sent to the database and to ignore the input file you could:
in the back-end don't consider the field;
you can set the disabled attribute to the input file before serialising the form;
remove the DOM element before sending data.
When you want to delete a file just get the index of the element and remove the input element (text or hidden) from the DOM.
Requirements:
You need to write the logic to convert files in base64 and store all files inside an array whenever the input file trigger the change event.
Pros:
This will basically give you a lot of control and you can filter, comparing files, check for file size, MIME type, and so on..

Based on #liamthorne4 answer, here is a working solution for upload, list and delete element from list, tested on Firefox and Chrome:
HTML:
<button onclick="uploadFile(event)">Upload files</button>
<div id="listfiles" class="view_list"></div>
<input class="hidden" type="file" id="input_file_id" onchange="fileList(event)" name="files[]" multiple>
JS:
function uploadFile(evt) {
evt.preventDefault();
$('#input_file_id').click();
}
function fileList(e) {
var files = $('#input_file_id').prop("files");
var names = $.map(files, function(val) { return val.name; });
for (n in names) {
$("#listfiles").append("<div id=preload_"+n+" title='"+names[n]+"'><p>"+names[n]+"</p><a onclick=deleteFile("+n+")>Delete</a></div>");
}
}
function deleteFile(index) {
filelistall = $('#input_file_id').prop("files");
var fileBuffer=[];
Array.prototype.push.apply( fileBuffer, filelistall );
fileBuffer.splice(index, 1);
const dT = new ClipboardEvent('').clipboardData || new DataTransfer();
for (let file of fileBuffer) { dT.items.add(file); }
filelistall = $('#input_file_id').prop("files",dT.files);
$("#preload_"+index).remove()
}

html
<input id="fileInput" name="fileInput" type="file" />
<input onclick="clearFileInput()" type="button" value="Clear" />
javascript
function clearFileInput(){
var oldInput = document.getElementById("fileInput");
var newInput = document.createElement("input");
newInput.type = "file";
newInput.id = oldInput.id;
newInput.name = oldInput.name;
newInput.className = oldInput.className;
newInput.style.cssText = oldInput.style.cssText;
// copy any other relevant attributes
oldInput.parentNode.replaceChild(newInput, oldInput);
}

Related

Form with Image Input type JavaScript React.js [duplicate]

How can I set the value of this?
<input type="file" />
You cannot set it to a client side disk file system path, due to security reasons.
Imagine:
<form name="foo" method="post" enctype="multipart/form-data">
<input type="file" value="c:/passwords.txt">
</form>
<script>document.foo.submit();</script>
You don't want the websites you visit to be able to do this, do you? =)
You can only set it to a publicly accessible web resource as seen in this answer, but this is clearly not the same as a client side disk file system path and it's therefore useless in that context.
You can't.
The only way to set the value of a file input is by the user to select a file.
This is done for security reasons. Otherwise you would be able to create a JavaScript that automatically uploads a specific file from the client's computer.
Not an answer to your question (which others have answered), but if you want to have some edit functionality of an uploaded file field, what you probably want to do is:
show the current value of this field by just printing the filename or URL, a clickable link to download it, or if it's an image: just show it, possibly as thumbnail
the <input> tag to upload a new file
a checkbox that, when checked, deletes the currently uploaded file. note that there's no way to upload an 'empty' file, so you need something like this to clear out the field's value
You can't. And it's a security measure. Imagine if someone writes JS that sets file input value to some sensitive data file?
I have write full example for load URL to input file, and preview
you can check here
1
https://vulieumang.github.io/vuhocjs/file2input-input2file/
in short you can use this function
function loadURLToInputFiled(url){
getImgURL(url, (imgBlob)=>{
// Load img blob to input
// WIP: UTF8 character error
let fileName = 'hasFilename.jpg'
let file = new File([imgBlob], fileName,{type:"image/jpeg", lastModified:new Date().getTime()}, 'utf-8');
let container = new DataTransfer();
container.items.add(file);
document.querySelector('#file_input').files = container.files;
})
}
// xmlHTTP return blob respond
function getImgURL(url, callback){
var xhr = new XMLHttpRequest();
xhr.onload = function() {
callback(xhr.response);
};
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.send();
}
As everyone else here has stated: You cannot upload just any file automatically with JavaScript.
HOWEVER! If you have access to the information you want to send in your code (i.e., not C:\passwords.txt), then you can upload it as a blob-type, and then treat it as a file.
What the server will end up seeing will be indistinguishable from someone actually setting the value of <input type="file" />. The trick, ultimately, is to begin a new XMLHttpRequest() with the server...
function uploadFile (data) {
// define data and connections
var blob = new Blob([JSON.stringify(data)]);
var url = URL.createObjectURL(blob);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'myForm.php', true);
// define new form
var formData = new FormData();
formData.append('someUploadIdentifier', blob, 'someFileName.json');
// action after uploading happens
xhr.onload = function(e) {
console.log("File uploading completed!");
};
// do the uploading
console.log("File uploading started!");
xhr.send(formData);
}
// This data/text below is local to the JS script, so we are allowed to send it!
uploadFile({'hello!':'how are you?'});
So, what could you possibly use this for? I use it for uploading HTML5 canvas elements as jpg's. This saves the user the trouble of having to open a file input element, only to select the local, cached image that they just resized, modified, etc.. But it should work for any file type.
You need to create a DataTransfer and set the .files property of the input.
const dataTransfer = new DataTransfer();
dataTransfer.items.add(myFile);//your file(s) reference(s)
document.getElementById('input_field').files = dataTransfer.files;
the subject is very old but I think someone can need this answer!
<input type="file" />
<script>
// Get a reference to our file input
const fileInput = document.querySelector('input[type="file"]');
// Create a new File object
const myFile = new File(['Hello World!'], 'myFile.txt', {
type: 'text/plain',
lastModified: new Date(),
});
// Now let's create a DataTransfer to get a FileList
const dataTransfer = new DataTransfer();
dataTransfer.items.add(myFile);
fileInput.files = dataTransfer.files;
</script>
Define in html:
<input type="hidden" name="image" id="image"/>
In JS:
ajax.jsonRpc("/consulta/dni", 'call', {'document_number': document_number})
.then(function (data) {
if (data.error){
...;
}
else {
$('#image').val(data.image);
}
})
After:
<input type="hidden" name="image" id="image" value="/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8U..."/>
<button type="submit">Submit</button>
Actually we can do it.
we can set the file value default by using webbrowser control in c# using FormToMultipartPostData Library.We have to download and include this Library in our project. Webbrowser enables the user to navigate Web pages inside form.
Once the web page loaded , the script inside the webBrowser1_DocumentCompleted will be executed.
So,
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
FormToMultipartPostData postData =
new FormToMultipartPostData(webBrowser1, form);
postData.SetFile("fileField", #"C:\windows\win.ini");
postData.Submit();
}
Refer the below link for downloading and complete reference.
https://www.codeproject.com/Articles/28917/Setting-a-file-to-upload-inside-the-WebBrowser-com

Retreiving contents of previously obtained text

This is a follow-up to a previous post (solved). In the previous post we loaded a delimited text file then took action on the contents of the file. But what we did was in one smooth progression of events. In my actual implementation, events will occur separately. First, a tab delimited text file will be loaded, using the FileReader API, and displayed on the page. Much later a function will need to retrieve the loaded content and do stuff with it. I thought I would have no difficulty separating the tasks, but I was wrong. I don't know what I'm doing wrong or if I'm going about it the wrong way. I'd appreciate some input.
Note: I don't necessarily have to use the information directly from the pre-tag "fileDisplayArea". I just thought that would work and be easy. I could use the string stored in memory, if that is better. The string should never be more than 6 or 7 Mb.
What do I need to do to, so at a later time I can use the string loaded and placed in "fileDisplayArea"?
Thanks in advance,
Andrew
var fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function (e) {
var file = fileInput.files[0];
var textType = /text.*/;
if (file.type.match(textType)) {
var reader = new FileReader();
reader.onload = function (e) {
// Entire file
fileDisplayArea.innerText = reader.result;
}
reader.readAsText(file);
} else {
fileDisplayArea.innerText = "File not supported!"
}
});
// doIt functionality
document.getElementById("doIt").addEventListener("click", function () {
var myTemp = document.getElementById("fileDisplayArea");
console.log(myTemp);
// trying to retreive original reader.result contents so I can do stuff with it
// i thought it would be as simple as using getElementByID, but i'm obviously wrong
}, false);
<br />
Step 1:<br />
Select a text file:
<input type="file" id="fileInput">
<hr />
Step 2:<br />
Retreive the contents previously loaded. (Normally 'doIt' would be called from another function, not a button.)
<button id="doIt">doIt</button>
<hr />
<pre id="fileDisplayArea"></pre>

Using Google Chrome extensions to import/export JSON files?

I'm creating a Google Chrome extension at the moment and I was wondering if it's possible for it to both create JSON files to download (export) and create a button where users can make the extension open and parse JSON files that they have saved in their local file system or on a USB stick (import)?
The parsing of each JSON from the local file system would simply involve reading off each key-value pair and doing something with the data. It would only have to deal with strings, so nothing complicated.
**EDIT: **My question is not a duplicate of this one because I'm not interested in changing the user's download path. All I want is to enable them to, with their consent, download a file to their normal download directory (which Filesaver.js can do). Plus, that post says nothing about importing.
You can fake link to "download" imaginary array MyData or whatever,:
var MyArray = [elem1, elem2, ....];
var _myArray = JSON.stringify(MyArray , null, 4); //indentation in json format, human readable
var vLink = document.createElement('a'),
vBlob = new Blob([_myArray], {type: "octet/stream"}),
vName = 'watever_you_like_to_call_it.json',
vUrl = window.URL.createObjectURL(vBlob);
vLink.setAttribute('href', vUrl);
vLink.setAttribute('download', vName );
vLink.click();
this will export/download your array into json file named as vName variable.
If you wish to import/read file:
create input element (type=file) and make it invisible (here I'm having html element and then adding js listener in script)
<input type="file" id="importOrig" accept=".json" style="display:none"/>
script
importOrig.addEventListener("change", importFun, false);
make button fakeImp (or any element), that you can style as you wish and that will be used as trigger for importing event
fakeImp.onclick = function () {importOrig.click()}
import function (from listener)
function importFun(e) {
var files = e.target.files, reader = new FileReader();
reader.onload = _imp;
reader.readAsText(files[0]);
}
function _imp() {
var _myImportedData = JSON.parse(this.result);
//here is your imported data, and from here you should know what to do with it (save it to some storage, etc.)
......
importOrig.value = ''; //make sure to clear input value after every import
}

error css class not applied in custom file input tag and jquery validation counting was not happening where unsupported format image upload

First of all Sorry for the length heading. Currently working on custom file input where with my current code i can able to upload the only jpeg file if the user uploading some other format it will show error message you have to upload only jpg
when the user click the next button jquery should validate the file input and it should say in the message you have missed one field currently I gave required for the input field still it was not validting the field. I am struggling lot not getting anything in my mind help me.
Here is the jquery code
function showImage() {
var files = !! this.files ? this.files : [];
var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.jpg|.jpeg)$/;
// No file selected, or no FileReader support
if (!files.length || !window.FileReader) return;
// If the file is a JPEG image
if (regex.test(files[0].type)) {
// Create an instance of FileReader
var reader = new FileReader();
// Declare the onload callback before reading the file
reader.onload = function () {
// Set image data as background of div
$preview.css("background-image", "url(" + this.result + ")");
// Empty the error message
$errorLabel.text('');
// Disable file selection
$fileInput.prop('disabled', true);
// Show the buttons
$deleteBtn.show();
$sendBtn.show();
$imagecontainer.hide();
};
// Read the local file
reader.readAsDataURL(files[0]);
} else {
// Add an error message
$errorLabel.text('Please upload only jpeg');
$errorLabel.css("color","red");
$fileInput.addClass('errRed');
}
}
Here is the fiddle link
Kindly please guide me
Thanks in advance
html code
<input name="Select File upload" accept="image/jpeg" required class="upload" id="upload" type="file" />
Now I gave new property call accept input file user can upload only jpeg image this was happening correctly but my validation count was not reduced with this :(
Your regex won't validate against the type attribute, as it returns the MIME type of the file, and your regex is looking at the file extension. Use the name attribute instead if you want to keep using that regex.
In other words, try changing
regex.test(files[0].type)
to
regex.test(files[0].name)
Finally after long hours i found the answer for this issue :) I need to put one single line that was the most funniest part here.
this is the line which was so much time i need to put this line in the condition :) $(".basicForm").validate().element("#upload");
if (regex.test(files[0].type)) {
// Create an instance of FileReader
var reader = new FileReader();
// Declare the onload callback before reading the file
reader.onload = function () {
// Set image data as background of div
$preview.css("background-image", "url(" + this.result + ")");
// Empty the error message
$errorLabel.text('');
//$('.choose_file').removeClass('errRed');
$(".basicForm").validate().element("#upload");
$('#imageUploadForm').removeClass('errRed');
// validate();
// Disable file selection
$fileInput.prop('disabled', true);
// Show the buttons
$deleteBtn.show();
$sendBtn.show();
$imagecontainer.hide();
};
// Read the local file
reader.readAsDataURL(files[0]);
} else {
//alert("sorry not an jpeg file");
// Add an error message
$(".basicForm").validate().element(".upload");
$fileInput.val('');
$errorLabel.text('Please upload only jpeg');
$errorLabel.css("color","red");
$fileInput.addClass('errRed');
//$(event).preventDefault();
var control = $("#files");
control.replaceWith( control = control.clone( true ) );
$(".btn-next").trigger('click');
}

Parse a local file to an array using JavaScript

I am trying to read a local file and have each line as an index in an array using JavaScript. I have been searching for the past 20 minutes and either I'm stupid or there really isn't an answer that pertains to my problem (...but it's probably the former :P). I am really new to JavaScript so if you have an answer could you please comment the code just to I know what's going on?
Also, from the searching I've done on the internet some people said JavaScript can't read local file for security reasons so if that is correct is there another language I can use? I'm a bit familiar with PHP if that is an option, which I doubt it is.
EDIT
As per thg435's question, I'll explain what I am trying to accomplish.
My project is to analyze a BUNCH of water quality data that has been collected by the Ontario gov't (which I've done) and display it in some way. I have chosen to display it on a webpage using the Google Maps API. I currently have a file of chemicals that were found. Each line is a different chemical. I would like to read the file in an array then create an option menu displaying the chemicals in the array.
Also, the local file I would like to read will the be the same name and location all the time. I have seen people have boxes where the user clicks and chooses their file or to drag and drop but that's not what I'm looking for.
I don't think I explained this properly. I have a file in the same directory as my HTML and JavaScript files that contains words. Example:
Line 1: "Iron"
Line 2: "Aluminum"
Line 3: "Steel"
etc...
I would like to read the file and parse each line into a different index in an array. I don't want the user to be able to choose which file to read using the <input ... /> thing.
You're going to want to take a look at the FileReader API. This should allow you to read the text of a local file via readAsText(). This won't work in every browser but should work in all modern browser. You can see which browsers support it here.
Example:
<input id="file" type="file" />
var filesInput = document.getElementById("file");
filesInput.addEventListener("change", function (event) {
var files = event.target.files;
var file = files[0];
var reader = new FileReader();
reader.addEventListener("load", function (event) {
var textFile = event.target;
alert(textFile.result);
});
reader.readAsText(file);
});
It's not possible to invoke the FileReader API without user interaction. Consequently, your user would have to select whatever file to load in order for it to be read in pure JS. Since I'm assuming this will be up on a server, why not just put the list of chemicals also up on the server and GET the JSON encoded array of the results. Then you can decode them with Javascript.
You can access local files in 2 ways that I know of. The first way is making the user drag-and-drop the files onto the page, and using an <input type="file"> tag.
For the former, you would need to do the following:
addEventListener('dragover', function(e){e.preventDefault();});
addEventListener('drop', function(e) {
eventHandler.call(e.dataTransfer||e.clipboardData);
e.preventDefault();
});
For the latter, you'd need to add an event listener for the change event on the input:
document.getElementById('upload').addEventListener('change', eventHandler)
And for both, you'd need to have this as a basic callback function:
function eventHandler() {
var file = this.files[0]; //get the files
var reader = new FileReader(); //initiate reader
reader.onloadend = callbackFn; //set event handler
reader.readAsText(file); //initiate reading of files
if (this.id) { //only run if this is the input
var id = this.id;
this.outerHTML = this.outerHTML; //this resets the input
document.getElementById(id).addEventListener('change', eventHandler); //reattach event handler
}
function callbackFn(e) {
document.getElementById('output').value = e.target.result; //output it to a textarea
}
}
Here is a demo where the text contents (that what you see when opening it in notepad) of any file you drop in it, or any file you select from the input, is put in the textarea.
For more information, see https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications.

Categories

Resources