Kushagra
Kushagra

Reputation: 655

Pass an HTML file object from one <input type = file> to another

I want to implement a multiple file uploader in a form wherein I want the files so that the user may sort the priority of the files (I am using draggable and sortable Jquery tool).

Therefore I have added a multiple file input as:

<input type = "file" multiple>

Now when I select some files, it shows say 3 files selected. But when I select 3 files, I wish to split the file uploader in 3 parts so that the user may set the priority ordering accordingly.

For that I have used the following kind of code:

$('.files').change(function(e){
var filesSelected = e.target.files;
if(filesSelected.length > 1){ //if user selects multiple files, then automatically split the files into multiple divs so that he/she may do the ordering of files
    //Here I want to create a list of  all the files and implement the draggable and sortable thing.
}
});

The situation is, that I am not able to split the array of objects of FileList and assign each object to another input.

Hope I am clear in my doubt and the question is understandable, as it is the first time I am posting in any such forum.

Upvotes: 11

Views: 7808

Answers (4)

Dhruv
Dhruv

Reputation: 91

Great that you found a workaround to your problem. Building on it, I have another problem. I want the user to be able to select multiple files, multiple times. But every time the user selects new files, old files are lost.

I am also building a multiple file uploader, for showcasing priority(sequence) and file preview (I am working with images). Since "input.files" is a read-only property, assigning new files to any input is not an option.

A workaround that has worked for me is

  1. Using a label for my input field, and hiding the input.
  2. After the user selects files, clone that input and remove the original input's ID (so that the label no longer refers to it). And adding the new input to the form.

This way the "name" of the input remains same, and when the form is submitted. All the files are sent.

This is HTML sample:

<label for="add-item-image-input" class="button">Upload Image +</label>
<input hidden multiple autocomplete="off" type="file" accept="image/jpeg, image/png" name="images" data-preview-table="add-item-image-preview-table" id="add-item-image-input" onchange="previewMyImages(this)" />

This is JavaScript snippet:

let previewTable = document.getElementById(inputElement.getAttribute("data-preview-table"));
let inputName = inputElement.getAttribute("name");
let newInput = inputElement.cloneNode();
inputElement.removeAttribute("id");

let form = inputElement.form;
let files = [];
Array.from(form.querySelectorAll(`input[name='${inputName}']`))
    .map((input) => (files = [...files, ...input.files]));
console.log(files);
inputElement.insertAdjacentElement("afterend", newInput);

However, this method introduces the risk of uploading the same file multiple times, but this can be prevented using extra logic.

Upvotes: 0

Kushagra
Kushagra

Reputation: 655

From the posts I received and the brief discussions, it is evident that setting file values programmatically will pose security threat and so is not a good option. As far as solving my issue is concerned, best would be to find a way to create multiple divs/fields containing the filenames of the files that are being uploaded and then applying the drag/drop/sort feature in that set of divs. This way the user can easily prioritize the files and while saving the form the array/field containing the priority shall be considered before saving the files data in the database.

Thanks to the responders for their quick response.

Upvotes: 1

Zoli Szab&#243;
Zoli Szab&#243;

Reputation: 4534

You cannot set value for <input type="file"> programmatically. It would be a major security flow. Imagine some website automatically uploading arbitrary files from your computer.

Upvotes: 5

You can try to iterate through the selected files and then create a div dynamically with jquery that contains the data from the file like this

$('.files').change(function(e){
var filesSelected = e.target.files;
if(filesSelected.length > 1){ 
   for(var i=0;i<filesSelected.length;i++) { // We iterate through the selected Files
      $("#idFromParentElement").append('<div> id=File'+i+'</div'); // Then we create and append the new div to the parent element of our choice
      var fileId = 'File'+i;
      $("#fileId").data("file",filesSelected[i]); //After that we include a data into the div with the selected file.
   }
}
});

Upvotes: 3

Related Questions