从不同文件夹上传 HTML 多个文件

Posted

技术标签:

【中文标题】从不同文件夹上传 HTML 多个文件【英文标题】:HTML multiple file upload from different folders 【发布时间】:2014-09-13 09:14:45 【问题描述】:

我有一个带有上传字段的表单,允许用户选择多个文件。但是,我需要能够允许用户从文件夹 1 中选择文件 1,然后从文件夹 2 中选择文件 2,依此类推。

目前,当用户从文件夹 1 中选择文件 1 然后点击“打开”时,选择窗口将关闭(将用户留在我的表单上)。然后,如果用户从文件夹 2 中选择文件 2 并点击“打开”按钮,文件 1 将被删除,只留下文件 2。

基本上,用户无法选择多个文件,除非它们都在同一个位置。选择文件 2 后,有没有办法让文件 1 保持选中状态?

【问题讨论】:

我很确定这是不可能的,文件选择窗口是由操作系统控制的。 这是正确的,但它是必要的 【参考方案1】:

这个怎么样?

该解决方案使用 html、jQuery/javascriptphp(用于服务器端处理此数据)。想法是: 1.) HTML 表单:包括一个“浏览”按钮,允许用户选择多个文件(在一个目录中)。 2.) jQuery:在表单中创建一个新按钮的选项,允许用户选择多个文件(在不同的目录中——甚至实际上是同一个目录!),具有“无限”创建新按钮的能力。 3.) PHP:作为奖励,我考虑了将数据很好地打包以供服务器端处理。

这是 HTML 表单的外观(我使用了一个可点击对象的找到图标,但您可以轻松地将其替换为您选择的图形)。

<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>

这是 jQuery/Javascript 在事件触发后创建一个新的“浏览”按钮(这甚至将它放在最后一个“浏览”按钮之后!):

<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>

最后,可能也是最重要的一点,如何以熟悉的格式包装服务器上的数据:

<?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++;
    

?>

更新说明: jQuery 脚本和 vanilla Javascript 实现相同的目标。我遇到了一个需要香草版本的问题。 您只需要其中一个

【讨论】:

【参考方案2】:

不,你不能。这是由操作系统定义的行为,并且可能因操作系统而异。你无法精确控制这些事情,你总是会害怕发生什么。

如果人们必须选择的文件夹数量非常少,您可以提供多个上传字段。

【讨论】:

【参考方案3】:

另一种解决方案是使用老式(非多个)文件输入。在这种情况下,您无法选择要上传的多个文件,但您可以删除任何文件并添加另一个文件。页面上最初只有一个文件输入,但当您选择一个文件时,它会隐藏并用删除按钮替换为文件名,并出现新的文件输入。

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>

【讨论】:

【参考方案4】:

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);
  
&lt;input type="file" multiple&gt;

【讨论】:

以上是关于从不同文件夹上传 HTML 多个文件的主要内容,如果未能解决你的问题,请参考以下文章

如何从不同来源的 Chrome 扩展程序提供文件?

如何在单个 TCP 数据包中从不同文件中分离数据?

从不同文件发送数据的简单 perl 程序

从不同文件添加项目并使用数组列表将它们存储在另一个文件中

从不同文件夹读取.png图片并保存到一个文件夹下

xcode更新从不同分支构建的PCH文件后的问题[重复]