处理从单个输入元素通过POST上传的多个文件

时间:2017-08-13 18:06:06

标签: javascript jquery ajax file-upload

我正在编写一个图片上传程序并让它与单个文件完美配合,但是当我尝试处理多个文件时,似乎没有任何东西可以通过。我有一个HTML元素来接受多个文件:

<input type="file" id="entryPhotos" multiple>

然后构建我的FormData

var formData = new FormData();
var entryArray = new Array("entryName","entryFoodType","entryROI","entryOpeningHour","entryOpeningMinute","entryOpeningAMPM","entryClosingHour","entryClosingMinute","entryClosingAMPM","entryPhone","entryEmail","entryPhotos","entryDesc","entryLocLat","entryLocLong");
for(var temp = 0; temp < entryArray.length; temp++){
    //--I suspect my problem is here
    if($('#' + entryArray[temp])[0].files){
        formData.append(entryArray[temp], $('#' + entryArray[temp])[0].files);
    }
    else{
        formData.append(entryArray[temp], $('#' + entryArray[temp]).val());
    }
}

之后使用jQuery.ajax发送它:

$.ajax({
    url: '/scripts/spotEntry.php',
    data: formData,
    type: 'POST',
    contentType: false,
    processData: false,
    success: function(returnCode){
        entryReturnProc(returnCode);
    }
});

但是当它到达服务器时没有任何东西:

echo count($_FILES["entryPhotos"]["name"]);   //returns 0

如果我只是做一张图片,我可以$('#' + entryArray[temp])[0].files[0]这样做就可以了,但是我不应该删除[0]并让它发送数组,从我的理解,FormData jQuery.ajax和PHP都支持?

2 个答案:

答案 0 :(得分:1)

对于任何可能遇到此问题的人。经过一番搜索后,我在这里找到了答案:uploading-multiple-files-using-formdata

我不得不稍微修改我的formData.append命令并遍历数组而不是仅传递整个事物:

var entryArray = new Array("entryName","entryFoodType","entryROI","entryOpeningHour","entryOpeningMinute","entryOpeningAMPM","entryClosingHour","entryClosingMinute","entryClosingAMPM","entryPhone","entryEmail","entryPhotos","entryDesc","entryLocLat","entryLocLong");
for(var temp = 0; temp < entryArray.length; temp++){
    if($('#' + entryArray[temp])[0].files){
        for (var i = 0; i < $('#' + entryArray[temp])[0].files.length; i++) {
            formData.append(entryArray[temp] + "[]", $('#' + entryArray[temp])[0].files[i]);
        }
    }
    else{
        formData.append(entryArray[temp], $('#' + entryArray[temp]).val());
    }
}

为了完成,如果它可以帮助将来的某个人,用PHP在服务器上进行处理:

for($i = 0; $i < count($_FILES["entryPhotos"]["name"]); $i++){
       $tmp_name = $_FILES["entryPhotos"]["tmp_name"][$i];
       if (!$tmp_name) continue;

       $name = basename($_FILES["entryPhotos"]["name"][$i]);

    if ($_FILES["entryPhotos"]["error"][$i] == UPLOAD_ERR_OK)
    {
        if ( move_uploaded_file($tmp_name, $uploaddir.$name) ){
            echo 'us';
        }
        else{
            echo 'uf';
        }
    }
    else{
        echo 'uf';
    }
}

编辑/注意:此上传脚本相当粗糙,存在一定的安全风险。上传文件时请始终牢记:永远不要相信用户上传的内容是安全的。始终尽可能地清理您的上传内容。此代码段中未显示的一件事是文件保存在webroot后面的文件夹中。这有助于防止潜在黑客从他们上传的脚本中访问。

还建议将文件名一起更改为随机且唯一的内容,同时检查文件扩展名。某些服务器设置为允许多个扩展,这可以提供一个开放。我在网上找到了一些方法来做这些事情,然后将它们混合在一起后,这就是我提出的方法:

为了获得一个随机且唯一的名称,我使用了$prefix = str_replace(array('.', ' '), '' , microtime());,它以微秒为单位提取当前的Unix时间,从而给出一个潜在黑客无法预测的数字,然后帮助确保唯一性,因为我循环遍历多个文件,我将循环索引添加到前缀的末尾。

然后我拉出了基本名称的扩展名。我使用pathinfo()而不是使用典型的strstr(basename($name), '.')来拉取扩展名。我发现这个优点是它将拉动所有文件扩展名,而不仅仅是最后一个。然后我根据接受的扩展名列表进行检查。如果它通过,则可以将其上载到webroot之前的目录。这个固有的额外步骤是,如果文件有多个扩展名,则会自动跳过,从而避免可能存在的安全风险。

最后一点是,有几个&#34;卫生&#34;我没有使用的技术,如检查图像大小和检查MIME类型,以验证文件是图像。实际图像(因此返回文件大小)可能包含恶意编码,MIME类型由客户端发送,因此可以伪造。这对我来说似乎没有给出实际的好处,所以我没有使用它们,但有些人可能认为没有太安全的东西,甚至还有其他措施可以采取。在处理用户输入时,无论如何,您应该尽可能多地进行研究并采取适当的预防措施,以确保您,您的数据和用户受到保护。

答案 1 :(得分:0)

我相信你需要PHP的$ _FILES变量。

<form method="post" action="upload-page.php" enctype="multipart/form-data">
  <input name="filesToUpload[]" id="filesToUpload" type="file" multiple="" />
</form>

if(count($_FILES['uploads']['filesToUpload'])) {
    foreach ($_FILES['uploads']['filesToUpload'] as $file) {

        //do your upload stuff here
        echo $file;

    }
}

使用JavaScript执行此操作将如下所示:

//get the input and UL list
var input = document.getElementById('filesToUpload');
var list = document.getElementById('fileList');

//empty list for now...
while (list.hasChildNodes()) {
    list.removeChild(ul.firstChild);
}

//for every file...
for (var x = 0; x < input.files.length; x++) {
    //add to list
    var li = document.createElement('li');
    li.innerHTML = 'File ' + (x + 1) + ':  ' + input.files[x].name;
    list.append(li);
}