提问者:小点点

AJAX多文件上传-识别原始元素?


假设一个HTML页面上存在多个上传输入类型,我希望能够获得随文件一起提交的每个文件上传的name属性,这样PHP服务器端就可以准确地确定哪个文件上传程序正在传递哪个文件。

我的代码:

$('.php-email-form').submit(function (event) {
  event.preventDefault();
  
  var form = $(this);
  var data = new FormData();
  
  // add datas of input not file to data object
  $.each($(':input', form).not(':input[type=submit]'), function(i, fields){
    data.append($(fields).attr('name'), $(fields).val());
    console.log($(fields).attr('name'), $(fields).val());
  });    
  
  // add data from inputs type file
  $.each($('input[type=file]', form)[0].files, function (i, file) {
    data.append(file.name, file);
    console.log(file.name);
    console.log($(this).attr('name')); // test, trying to get the name attribute of input type file
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="php-email-form" enctype="multipart/form-data">
  <input type="text" name="test" value="value"><br>
  <input type="file" class="custom-file-input" id="photo" name="photo"><br>
  <input type="submit">
</form>

在PHP中查看$\u文件数组时,我得到以下输出:

array(1) { ["test"]=> string(5) "value" }

array(1) { ["IMG_8085_JPG"]=> array(5) { ["name"]=> string(12) "IMG_8085.JPG" ["type"]=> string(10) "image/jpeg" ["tmp_name"]=> string(14) "/tmp/phpxsP6RN" ["error"]=> int(0) ["size"]=> int(65949) } }

如上所述,上面图像的索引是图像名称(IMG_8085_JPG),尽管我希望这个索引是它来自的原始输入的名称。(照片或照片-2)

因此,如果在photo元素中上载了图像,则数组应如下所示:

array(1) { ["test"]=> string(5) "value" }

array(1) { ["photo"]=> array(5) { ["name"]=> string(12) "IMG_8085.JPG" ["type"]=> string(10) "image/jpeg" ["tmp_name"]=> string(14) "/tmp/phpxsP6RN" ["error"]=> int(0) ["size"]=> int(65949) } }

似乎name索引在上传文件时被覆盖在元素上,因此$(this). attr(name)不再引用属性,而是成为上传文件的名称。

我将所有jQuery代码发布在下面:

$('.php-email-form').submit(function (event) {
    event.preventDefault();

    var form = $(this);     
    var formAction = $(form).attr('action');
    var data = new FormData();

    // add data from inputs type text
    $.each($(':input', form).not(':input[type=submit]'), function(i, fields){
      data.append($(fields).attr('name'), $(fields).val());
    });    

    // add data from inputs type file
    $.each($('input[type=file]', form)[0].files, function (i, file) {
      data.append(file.name, file);
      console.log(file);
      console.log($(this).attr('name'));
    });

    $('.loading').fadeIn();

    $.ajax({
      url: formAction,
      type: "POST",
      data: data,
      contentType: false,
      cache: false,
      processData: false,
    }).done(function(data){
      $('.loading').hide();
      $('.sent-message').fadeIn().html(data);
    }).fail(function(jqXHR, textStatus, errorThrown) {
      $('.loading').hide();
      $('.error-message').show().html(errorThrown);
    });
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

当我使用var\u dump$\u POST时所期望的结果

array(1) { ["test"]=> string(5) "value" }


array(1) { ["photo"]=> array(5) { ["name"]=> string(12) "IMG_8085.JPG" ["type"]=> string(10) "image/jpeg" ["tmp_name"]=> string(14) "/tmp/phpxsP6RN" ["error"]=> int(0) ["size"]=> int(65949) } } 

共2个答案

匿名用户

您直接迭代每个输入的文件,而不是元素本身,这使得type属性可以访问。

$.each($('input[type=file]', form), function(i, file) { // Iterate through every file upload element.
    let uploadedFile = this.files[0]; // Get the file that was uploaded to this input.
    data.append(this.name, uploadedFile); // Append it to the form data under the index of the name of the input it was provided in.

    // Testing.
    console.log(this.name); // input name (in this case, 'photo')
    console.log(uploadedFile); // uploaded file element object.
});

这里的区别在于,当您在中迭代时('input[type=file]',form)[0]。文件,您将直接访问这些文件,并且无法访问它们来自的父输入,因为没有对它们的引用。

解决方案是使用“文件”类型迭代每个输入,这样我们仍然可以获取每个输入并访问“名称”属性,然后我们可以获取在循环中上传的文件本身,this.files[0].(获取第一个上传的文件。)

匿名用户

代码中缺少的主要内容是表单的enctype属性。无论何时在表单中使用文件输入,都必须将enctype指定为多部分/表单数据

将表单标记更改为:

<form class="php-email-form" enctype="multipart/form-data">

现在,您可以简单地发送表单(无需手动赋值)

$('.php-email-form').submit(function(event) {
    event.preventDefault();
    var myFormData = new FormData($(this)[0]);
    $.ajax({
        type: 'POST',
        url: 'test-dest.php',
        data: myFormData,
        contentType: false,
        processData: false,
        cache: false,
        success: function(data) {
            console.log(data);
        }
    });
});

并从测试目的地回显$\u文件。php使用

echo var_dump($_FILES);

这将给你的结果在

    array(1) {
  ["photo"]=>
  array(5) {
    ["name"]=>
    string(14) "web-design.png"
    ["type"]=>
    string(9) "image/png"
    ["tmp_name"]=>
    string(25) "D:\myfolder\tmp\phpC00E.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(4001)
  }
}