HTML multiple file upload from different folders

≡放荡痞女 提交于 2019-11-29 11:04:26

No, you can't. This is a behaviour defined by the operating systems and may vary between them. You can't control these things precisly and you will always fear what happen.

If the amount of folders people have to choose is quite small you could offer multiple upload fields.

How about this?

The solution uses HTML, jQuery/Javascript, and PHP (for server-side handling of this data). The idea is: 1.) HTML Form: Includes one "browse" button that allows the user to select multiple files (within one directory). 2.) jQuery: The option to create a new button in the form that allows users to select multiple files (within a different directory -- or even the same one actually!), with the ability to create new buttons "infinitely". 3.) PHP: As a bonus, I put some thought into packaging the data nicely for server-side handling.

Here is what the HTML form could look like (I used a found-icon for the clickable object, but you can easily replace it with a graphic of your choosing).

<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" enctype='multipart/form-data'>
    Select files: <br/>
    <input type='file' name='files0[]' id="files0" multiple><br/><br/><br/>
    <span style="font-size: 10pt;">Click "+" for more files
    <i id="more_files" class="general foundicon-plus" style="color: blue;cursor: pointer;"></i></span>
    <br/><br/><br/>
    <input type="submit" name="submit" value="Submit">
</form>

Here is the jQuery/Javascript to create a new "browse" button once the event is triggered (this even places it after the LAST "browse" button!):

<script type="text/javascript">
//jQuery
$(document).ready(function() {
    $(document).on('click','#more_files', function() {
        var numOfInputs = 1;
        while($('#files'+numOfInputs).length) { numOfInputs++; }//once this loop breaks, numOfInputs is greater than the # of browse buttons

        $("<input type='file' multiple/>")
            .attr("id", "files"+numOfInputs)
            .attr("name", "files"+numOfInputs+"[]")
            .insertAfter("#files"+(numOfInputs-1));

        $("<br/>").insertBefore("#files"+numOfInputs);
    });
});
</script>
<script>
    //vanilla javascript version
    var location = document.getElementById("fileBrowsers");
    var br = document.createElement("BR");
    location.appendChild(br);
    var input = document.createElement("input");
    input.type = "file";
    input.name = "files"+numOfInputs+"[]";
            input.id = "files"+numOfInputs;
            input.multiple = true;

            location.appendChild(input);
</script>

Finally, and possibly most important, how to wrap up the data on the server in a familiar format:

<?php
if(isset($_POST['submit']) && !empty($_FILES)) {
    $files = array();
    $files = $_FILES['files0'];
    //var_dump($files);//this array will match the structure of $_FILES['browser']
    //Iterate through each browser button
    $browserIterator = 1;
    while(isset($_FILES['files'.$browserIterator])) {
        //Files have same attribute structure, so grab each attribute and append data for each attribute from each file
        foreach($_FILES['files'.$browserIterator] as $attr => $values) {//get each attribute
            foreach($_FILES['files'.$browserIterator][$attr] as $fileValue) {//get each value from attribute
                $files[$attr][] = $fileValue;//append value
            }
        }
        $browserIterator++;
    }
    //Use $files like you would use $_FILES['browser'] -- It is as though all files came from one browser button!
    $fileIterator = 0;
    while($fileIterator < count($files['name'])) {
        echo $files['name'][$fileIterator]."<br/>";
        $fileIterator++;
    }
}
?>

Update Note: jQuery script and vanilla Javascript accomplish the same goal. I ran into an issue that required the vanilla version. You only need one of them.

Another solution is using old school (non-multiple) file inputs. In this case you cannot select multiple files to upload, but you can remove any file and add another. Initially there is only one file input on page, but when you select file, it hiding and replacing by filename with delete button, and new file input appears.

var fileInput = document.getElementById('fileInput_0');
var filesList =  document.getElementById('fileList');  
var idBase = "fileInput_";
var idCount = 0;

var inputFileOnChange = function() {

	var existingLabel = this.parentNode.getElementsByTagName("LABEL")[0];
	var isLastInput = existingLabel.childNodes.length<=1;

	if(!this.files[0]) {
		if(!isLastInput) {
			this.parentNode.parentNode.removeChild(this.parentNode);
		}
		return;
	}

	var filename = this.files[0].name;

	var deleteButton = document.createElement('span');
	deleteButton.innerHTML = '&times;';
	deleteButton.onclick = function(e) {
		this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);
	}
	var filenameCont = document.createElement('span');
	filenameCont.innerHTML = filename;
	existingLabel.innerHTML = "";
	existingLabel.appendChild(filenameCont);
	existingLabel.appendChild(deleteButton);
	
	if(isLastInput) {	
		var newFileInput=document.createElement('input');
		newFileInput.type="file";
		newFileInput.name="file[]";
		newFileInput.id=idBase + (++idCount);
		newFileInput.onchange=inputFileOnChange;
		var newLabel=document.createElement('label');
		newLabel.htmlFor = newFileInput.id;
		newLabel.innerHTML = '+';
		var newDiv=document.createElement('div');
		newDiv.appendChild(newFileInput);
		newDiv.appendChild(newLabel);
		filesList.appendChild(newDiv);
	} 
}

fileInput.onchange=inputFileOnChange;
#fileList > div > label > span:last-child {
	color: red;
	display: inline-block;
	margin-left: 7px;
	cursor: pointer;
}
#fileList input[type=file] {
	display: none;
}
#fileList > div:last-child > label {
	display: inline-block;
	width: 23px;
	height: 23px;
	font: 16px/22px Tahoma;
	color: orange;
	text-align: center;
	border: 2px solid orange;
	border-radius: 50%;
}
<form enctype="multipart/form-data" method="post">
	<div id="fileList">
		<div>
			<input id="fileInput_0" type="file" name="file[]" />
			<label for="fileInput_0">+</label>      
		</div>
	</div>
</form>

document.querySelector("input").addEventListener("change", list_files);

function list_files() {
  var files = this.files;
  for (var i = 0; i < files.length; i++) {
    console.log(files[i].name);
  }
}
<input type="file" multiple>
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!