如何使用PHP、jQuery和AJAX上传多个文件

48

我设计了一个简单的表单,允许用户将文件上传到服务器。最初,该表单包含一个“浏览”按钮。如果用户想要上传多个文件,则需要单击“添加更多文件”按钮,这会在表单中添加另一个“浏览”按钮。当提交表单时,文件上传过程由'upload.php'文件处理。它适用于上传多个文件。现在我需要使用jQuery的'.submit()'提交表单并发送ajax['.ajax()']请求到'upload.php'文件以处理文件上传。

这是我的HTML表单:

<form enctype="multipart/form-data" action="upload.php" method="post">
    <input name="file[]" type="file" />
    <button class="add_more">Add More Files</button>
    <input type="button" id="upload" value="Upload File" />
</form>

这里是 JavaScript 代码:

$(document).ready(function(){
    $('.add_more').click(function(e){
        e.preventDefault();
        $(this).before("<input name='file[]' type='file' />");
    });
});

以下是文件上传处理的代码:

for($i=0; $i<count($_FILES['file']['name']); $i++){
$target_path = "uploads/";
$ext = explode('.', basename( $_FILES['file']['name'][$i]));
$target_path = $target_path . md5(uniqid()) . "." . $ext[count($ext)-1]; 

if(move_uploaded_file($_FILES['file']['tmp_name'][$i], $target_path)) {
    echo "The file has been uploaded successfully <br />";
} else{
    echo "There was an error uploading the file, please try again! <br />";
}
任何对我该如何编写“.submit()”函数的建议都将非常有帮助。

我认为你应该使用这些过程中的一个,要么提交,要么通过ajax上传。你想要什么不太清楚。 - Manish Shukla
1
类似的问题有可能有解决方案。如何使用jQuery异步上传文件。 - Awemo
无论提交还是上传都可以,但文件上传是主要优先事项。 - Rivnat
4个回答

61

最终我通过使用以下代码找到了解决方案:

$('body').on('click', '#upload', function(e){
        e.preventDefault();
        var formData = new FormData($(this).parents('form')[0]);

        $.ajax({
            url: 'upload.php',
            type: 'POST',
            xhr: function() {
                var myXhr = $.ajaxSettings.xhr();
                return myXhr;
            },
            success: function (data) {
                alert("Data Uploaded: "+data);
            },
            data: formData,
            cache: false,
            contentType: false,
            processData: false
        });
        return false;
});

为什么不接受Kalai的答案呢?它几乎涵盖了你所需要的一切。 - Onimusha
18
Kalai的回答有多个错误。这就是我没有接受的原因。但是我很高兴和感激他的帮助之意。 - Rivnat
2
不错且简单的解决方案,尽管在您发布的代码中,您忘记在末尾加上一个 ; 了。 - skechav
@V.P 你可以使用超全局变量 $_FILES 在 PHP 中访问已提交的文件相关数据。 - Rivnat
@V.P 正如我之前的评论中所提到的,您可以使用$_FILES来访问与文件相关的数据。但是,如果您提交了其他表单元素,您可以使用$_POST来访问它们。如果您认为这些截图中的代码能够满足您的需求,那么您就可以使用它们。 - Rivnat
显示剩余9条评论

53

HTML

<form enctype="multipart/form-data" action="upload.php" method="post">
    <input name="file[]" type="file" />
    <button class="add_more">Add More Files</button>
    <input type="button" value="Upload File" id="upload"/>
</form>

Javascript

 $(document).ready(function(){
    $('.add_more').click(function(e){
        e.preventDefault();
        $(this).before("<input name='file[]' type='file'/>");
    });
});

用于Ajax上传

$('#upload').click(function() {
    var filedata = document.getElementsByName("file"),
            formdata = false;
    if (window.FormData) {
        formdata = new FormData();
    }
    var i = 0, len = filedata.files.length, img, reader, file;

    for (; i < len; i++) {
        file = filedata.files[i];

        if (window.FileReader) {
            reader = new FileReader();
            reader.onloadend = function(e) {
                showUploadedItem(e.target.result, file.fileName);
            };
            reader.readAsDataURL(file);
        }
        if (formdata) {
            formdata.append("file", file);
        }
    }
    if (formdata) {
        $.ajax({
            url: "/path to upload/",
            type: "POST",
            data: formdata,
            processData: false,
            contentType: false,
            success: function(res) {

            },       
            error: function(res) {

             }       
             });
            }
        });

PHP

for($i=0; $i<count($_FILES['file']['name']); $i++){
    $target_path = "uploads/";
    $ext = explode('.', basename( $_FILES['file']['name'][$i]));
    $target_path = $target_path . md5(uniqid()) . "." . $ext[count($ext)-1]; 

    if(move_uploaded_file($_FILES['file']['tmp_name'][$i], $target_path)) {
        echo "The file has been uploaded successfully <br />";
    } else{
        echo "There was an error uploading the file, please try again! <br />";
    }
}

/** 
    Edit: $target_path variable need to be reinitialized and should 
    be inside for loop to avoid appending previous file name to new one. 
*/

请使用上面的脚本来进行ajax上传。它会起作用。

1
对于变量filedata = document.getElementByName("file"),它显示“TypeError: document.getElementByName不是一个函数”。 - Rivnat
2
仍然显示“TypeError:filedata.files未定义”对于“var i = 0,len = filedata.files.length,img,reader,file;”。 - Rivnat
2
@Kalai:显示出了“showUploadedItem未定义”的错误。我该怎么办才能修复它? - RobertH
2
它仍在重新加载我的页面。 - mujaffars
3
“filedata = document.getElementsByName("file");”这行代码出现了错误:“filedata.files is undefined”。请问您需要的翻译是否正确? - V.P
显示剩余6条评论

4
使用此源代码,您可以通过ajax逐个上传多个文件,就像谷歌一样。您还可以查看上传进度。

HTML

 <input type="file" id="multiupload" name="uploadFiledd[]" multiple >
 <button type="button" id="upcvr" class="btn btn-primary">Start Upload</button>
 <div id="uploadsts"></div>

Javascript

    <script>

    function uploadajax(ttl,cl){

    var fileList = $('#multiupload').prop("files");
    $('#prog'+cl).removeClass('loading-prep').addClass('upload-image');

    var form_data =  "";

    form_data = new FormData();
    form_data.append("upload_image", fileList[cl]);


    var request = $.ajax({
              url: "upload.php",
              cache: false,
              contentType: false,
              processData: false,
              async: true,
              data: form_data,
              type: 'POST', 
              xhr: function() {  
                  var xhr = $.ajaxSettings.xhr();
                  if(xhr.upload){ 
                  xhr.upload.addEventListener('progress', function(event){
                      var percent = 0;
                      if (event.lengthComputable) {
                          percent = Math.ceil(event.loaded / event.total * 100);
                      }
                      $('#prog'+cl).text(percent+'%') 
                   }, false);
                 }
                 return xhr;
              },
              success: function (res, status) {
                  if (status == 'success') {
                      percent = 0;
                      $('#prog' + cl).text('');
                      $('#prog' + cl).text('--Success: ');
                      if (cl < ttl) {
                          uploadajax(ttl, cl + 1);
                      } else {
                          alert('Done');
                      }
                  }
              },
              fail: function (res) {
                  alert('Failed');
              }    
          })
    }

    $('#upcvr').click(function(){
        var fileList = $('#multiupload').prop("files");
        $('#uploadsts').html('');
        var i;
        for ( i = 0; i < fileList.length; i++) {
            $('#uploadsts').append('<p class="upload-page">'+fileList[i].name+'<span class="loading-prep" id="prog'+i+'"></span></p>');
            if(i == fileList.length-1){
                uploadajax(fileList.length-1,0);
            }
         }
    });
    </script>

PHP

upload.php
    move_uploaded_file($_FILES["upload_image"]["tmp_name"],$_FILES["upload_image"]["name"]);

您可以使用jQuery Ajax和PHP上传图像/文件,就像Google上传一样。文件将一个接一个地上传,而不是在一个请求中全部上传... - Milan Krushna
1
当我尝试运行它时,它什么也没做,这个JavaScript代码有错误吗? - Mr Castrovinci

3

我的解决方案

  • 假设表单id = "my_form_id"
  • 它从HTML中检测到表单的方法和表单的操作

jQuery 代码

$('#my_form_id').on('submit', function(e) {
    e.preventDefault();
    var formData = new FormData($(this)[0]);
    var msg_error = 'An error has occured. Please try again later.';
    var msg_timeout = 'The server is not responding';
    var message = '';
    var form = $('#my_form_id');
    $.ajax({
        data: formData,
        async: false,
        cache: false,
        processData: false,
        contentType: false,
        url: form.attr('action'),
        type: form.attr('method'),
        error: function(xhr, status, error) {
            if (status==="timeout") {
                alert(msg_timeout);
            } else {
                alert(msg_error);
            }
        },
        success: function(response) {
            alert(response);
        },
        timeout: 7000
    });
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接