如何使用jQuery异步上传文件?

How can I upload files asynchronously with jQuery?

提问人:Sergio del Amo 提问时间:10/3/2008 最后编辑:CommunitySergio del Amo 更新时间:5/22/2023 访问量:1495322

问:

我想使用jQuery异步上传文件。

$(document).ready(function () {
    $("#uploadbutton").click(function () {
        var filename = $("#file").val();

        $.ajax({
            type: "POST",
            url: "addFile.do",
            enctype: 'multipart/form-data',
            data: {
                file: filename
            },
            success: function () {
                alert("Data Uploaded: ");
            }
        });
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<span>File</span>
<input type="file" id="file" name="file" size="10"/>
<input id="uploadbutton" type="button" value="Upload"/>

我没有上传文件,而是只得到文件名。我能做些什么来解决这个问题?

javascript jquery ajax 异步 xmlhttprequest

评论

78赞 Jimmy 11/4/2009
您只获得文件名,因为您的 var 文件名获取的值为 $('#file'),而不是输入中的文件
22赞 Ashish Panery 4/13/2013
这是一个很好的例子: http://blueimp.github.io/jQuery-File-Upload/ - HTML5 ajax 上传 - 为不受支持的浏览器优雅回退到 iframe - 多文件异步上传 我们已经使用过它,效果很好。(文档在这里)
3赞 Federico J. 1/15/2014
还要检查这个:stackoverflow.com/questions/6974684/...,这里解释了如何通过jQuery实现它
2赞 alex 12/6/2014
@Jimmy 他将如何获取位于输入中的获取文件?
0赞 Cheery 10/15/2008
有各种现成的插件可以为jQuery进行文件上传。进行这种上传黑客并不是一种愉快的体验,因此人们喜欢使用现成的解决方案。这里有几个: - JQuery 文件上传器 - 多文件上传插件 - 迷你多文件上传 - jQuery 文件上传 您可以在 NPM(使用“jquery-plugin”作为关键字)或 Github 上搜索更多项目。

答:

108赞 Mattias 10/3/2008 #1

注意:这个答案已经过时了,现在可以使用 XHR 上传文件。


不能使用 XMLHttpRequest (Ajax) 上传文件。您可以使用 iframe 或 Flash 模拟效果。优秀的jQuery表单插件,可通过iframe发布文件以获得效果。

评论

18赞 Alleo 11/4/2011
小评论:在最新版本的 chrome 和 firefox 中,这是可能的,stackoverflow.com/questions/4856917/......
304赞 Oli 10/3/2008 #2

2019年更新:这仍然取决于您的人口统计使用的浏览器。

对于“新”HTML5 API,需要了解的重要一点是,直到 IE 10 才支持它。如果你的目标特定市场对旧版 Windows 的倾向高于平均水平,则你可能无法访问它。file

截至 2017 年,大约 5% 的浏览器是 IE 6、7、8 或 9 之一。如果你进入一家大公司(例如,这是一个B2B工具或你为培训提供的东西),这个数字可能会飙升。2016 年,我与一家公司打交道,该公司在超过 60% 的机器上使用 IE8。

现在是 2019 年,距离我最初的答案已经过去了将近 11 年。IE9 及更低版本在全球范围内都在 1% 左右,但仍有更高的使用率集群。

从中得出的重要结论是,无论功能如何,请检查您的用户使用的浏览器。如果你不这样做,你就会学到一个快速而痛苦的教训,即为什么“对我有用”在交付给客户的成果中不够好。Caniuse 是一个有用的工具,但请注意他们从哪里获得人口统计数据。它们可能与你的不一致。这一点从未比企业环境更真实。

以下是我2008年的回答。


但是,有一些可行的非 JS 文件上传方法。您可以在页面上创建一个 iframe(使用 CSS 隐藏),然后将表单定位到该 iframe。主页不需要移动。

这是一个“真实”的帖子,所以它不是完全互动的。如果你需要状态,你需要一些东西在服务器端来处理它。这因您的服务器而异。ASP.NET 有更好的机制。PHP普通失败,但你可以使用Perl或Apache修改来绕过它。

如果您需要上传多个文件,最好一次上传一个文件(以克服最大文件上传限制)。将第一个表单发布到 iframe,使用上述方法监视其进度,完成后,将第二个表单发布到 iframe,依此类推。

或者使用 Java/Flash 解决方案。他们在处理帖子方面更加灵活......

评论

145赞 meleyal 3/25/2011
作为记录,如果浏览器支持文件 API,现在可以进行纯 AJAX 文件上传 - developer.mozilla.org/en/using_files_from_web_applications
0赞 Brett Caswell 10/29/2015
这是一个相当古老的答案,但它有点误导。IE 早在 IE7 就原生支持 XHR,并且早在 IE5 就通过 ActiveX 支持它。w3schools.com/ajax/ajax_xmlhttprequest_create.asp。这样做的实际方法当然是针对 flash (shockwave) 组件,或推出 Flash/ActiveX (Silverlight) 控件。如果你可以通过 javascript 发起请求并处理响应,那就是 ajax。话虽如此,Ajax 是 XHR 的同义词,但它本身并没有描述传递/交换有效负载的下划线机制/组件。
5赞 Oli 10/29/2015
@BrettCaswell我并不是说 AJAX/XHR 是不可能的,只是说不可能在旧的 - 但永远存在的 - 版本的IE上发布文件。这过去是,现在仍然是完全正确的。
34赞 Darryl Hein 10/19/2008 #3

我发现的一个解决方案是将目标设置为隐藏的 iFrame。然后,iFrame 可以运行 JS 向用户显示它已完成(在页面加载时)。<form>

121赞 pixxaar 11/22/2008 #4

为此,我建议使用 Fine Uploader 插件。您的代码将是:JavaScript

$(document).ready(function() {
  $("#uploadbutton").jsupload({
    action: "addFile.do",
    onComplete: function(response){
      alert( "server response: " + response);
    }
  });
});

评论

36赞 Trantor Liu 7/23/2012
“这个插件是在 GNU GPL 2 或更高版本和 GNU LGPL 2 或更高版本下开源的。”因此,只要您不分发副本或修改后的版本,就不必打开您的项目。
2赞 Nick Albrecht 7/29/2021
如果有人试图走这条路,FineUploader 已于 2018 年停产。github.com/FineUploader/fine-uploader/issues/2073
35赞 wbharding 8/14/2009 #5

我已经在 Rails 环境中写了这篇文章。如果您使用轻量级的 jQuery-form 插件,它只有大约五行 JavaScript。

挑战在于如何让 AJAX 上传正常工作,因为该标准不理解多部分表单提交。它不会将 Rails 通过 AJAX 请求请求返回的文件数据发送回去。remote_form_for

这就是jQuery-form插件发挥作用的地方。

下面是它的 Rails 代码:

<% remote_form_for(:image_form, 
                   :url => { :controller => "blogs", :action => :create_asset }, 
                   :html => { :method => :post, 
                              :id => 'uploadForm', :multipart => true }) 
                                                                        do |f| %>
 Upload a file: <%= f.file_field :uploaded_data %>
<% end %>

下面是关联的 JavaScript:

$('#uploadForm input').change(function(){
 $(this).parent().ajaxSubmit({
  beforeSubmit: function(a,f,o) {
   o.dataType = 'json';
  },
  complete: function(XMLHttpRequest, textStatus) {
   // XMLHttpRequest.responseText will contain the URL of the uploaded image.
   // Put it in an image element you create, or do with it what you will.
   // For example, if you have an image elemtn with id "my_image", then
   //  $('#my_image').attr('src', XMLHttpRequest.responseText);
   // Will set that image tag to display the uploaded image.
  },
 });
});

这是 Rails 控制器的动作,非常普通:

 @image = Image.new(params[:image_form])
 @image.save
 render :text => @image.public_filename

在过去的几周里,我一直在 Bloggity 中使用它,它就像一个冠军一样工作。

88赞 Jordan Warbelow-Feldstein 7/29/2011 #6

这个 AJAX 文件上传 jQuery 插件上传文件,并将 对回调的响应,仅此而已。

  • 它不依赖于特定的 HTML,只需给它一个<input type="file">
  • 它不需要您的服务器以任何特定方式进行响应
  • 无论您使用多少个文件,或者它们在页面上的位置,都无关紧要

-- 使用最少 --

$('#one-specific-file').ajaxfileupload({
  'action': '/upload.php'
});

-- 或者多达 --

$('input[type="file"]').ajaxfileupload({
  'action': '/upload.php',
  'params': {
    'extra': 'info'
  },
  'onComplete': function(response) {
    console.log('custom handler for file:');
    alert(JSON.stringify(response));
  },
  'onStart': function() {
    if(weWantedTo) return false; // cancels upload
  },
  'onCancel': function() {
    console.log('no file selected');
  }
});
2624赞 olanod 1/6/2012 #7

使用 HTML5,您可以使用 Ajax 和 jQuery 上传文件。不仅如此,您还可以执行文件验证(名称、大小和 MIME 类型)或使用 HTML5 进度标记(或 div)处理 progress 事件。最近我不得不制作一个文件上传器,但我不想使用 Flash、Iframe 或插件,经过一番研究,我想出了解决方案。

The HTML:

<form enctype="multipart/form-data">
    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>
<progress></progress>

首先,如果需要,可以进行一些验证。例如,在文件的情况下:.on('change')

$(':file').on('change', function () {
  var file = this.files[0];

  if (file.size > 1024) {
    alert('max upload size is 1k');
  }

  // Also see .name, .type
});

现在,单击按钮即可提交:$.ajax()

$(':button').on('click', function () {
  $.ajax({
    // Your server script to process the upload
    url: 'upload.php',
    type: 'POST',

    // Form data
    data: new FormData($('form')[0]),

    // Tell jQuery not to process data or worry about content-type
    // You *must* include these options!
    cache: false,
    contentType: false,
    processData: false,

    // Custom XMLHttpRequest
    xhr: function () {
      var myXhr = $.ajaxSettings.xhr();
      if (myXhr.upload) {
        // For handling the progress of the upload
        myXhr.upload.addEventListener('progress', function (e) {
          if (e.lengthComputable) {
            $('progress').attr({
              value: e.loaded,
              max: e.total,
            });
          }
        }, false);
      }
      return myXhr;
    }
  });
});

如您所见,使用 HTML5(和一些研究)文件上传不仅成为可能,而且变得非常容易。尝试使用 Google Chrome,因为示例中的一些 HTML5 组件并非在每个浏览器中都可用。

评论

4赞 Dan 6/5/2012
我有文件部分工作...但是您也可以在其中包含文本字段吗?这似乎与或?var formData = new FormData($('form')[0]);serialize()
18赞 Alessandro Cosentino 11/2/2012
那么,我可以在上传中使用 _FILES 美元吗.php?
74赞 Tyler 1/3/2013
这应该适用于 Internet Explorer,但仅适用于版本 10。(caniuse.com/xhr2)
20赞 Shumii 6/1/2013
嗨,我很欣赏PHP是你选择的语言......但我想知道您是否知道这是否也适用于 ASP.NET MVC?我是一名 .NET 开发人员,我试图利用您的简单示例来上传一些 AJAX 文件,但在服务器端我没有得到我通过 AJAX 发布的文件。我使用的是最新的 Chrome。
29赞 BorisOkunskiy 9/12/2013
FormData在这里发挥了所有的魔力。请务必查看这些文档——它涵盖了您关于多个文件和字段的所有问题。
65赞 Techie 1/25/2013 #8

我一直在使用下面的脚本上传图像,这恰好可以正常工作。

[HTML全文]

<input id="file" type="file" name="file"/>
<div id="response"></div>

JavaScript的

jQuery('document').ready(function(){
    var input = document.getElementById("file");
    var formdata = false;
    if (window.FormData) {
        formdata = new FormData();
    }
    input.addEventListener("change", function (evt) {
        var i = 0, len = this.files.length, img, reader, file;

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

            if (!!file.type.match(/image.*/)) {
                if ( window.FileReader ) {
                    reader = new FileReader();
                    reader.onloadend = function (e) {
                        //showUploadedItem(e.target.result, file.fileName);
                    };
                    reader.readAsDataURL(file);
                }

                if (formdata) {
                    formdata.append("image", file);
                    formdata.append("extra",'extra-data');
                }

                if (formdata) {
                    jQuery('div#response').html('<br /><img src="ajax-loader.gif"/>');

                    jQuery.ajax({
                        url: "upload.php",
                        type: "POST",
                        data: formdata,
                        processData: false,
                        contentType: false,
                        success: function (res) {
                         jQuery('div#response').html("Successfully uploaded");
                        }
                    });
                }
            }
            else
            {
                alert('Not a vaild image!');
            }
        }

    }, false);
});

解释

我使用响应来显示上传动画和上传完成后的响应。div

最好的部分是,当你使用此脚本时,你可以随文件一起发送额外的数据,如ids等。我在剧本中提到了它。extra-data

在PHP级别,这将像普通的文件上传一样工作。额外的数据可以作为数据进行检索。$_POST

在这里,您没有使用插件之类的东西。您可以根据需要更改代码。你不是在这里盲目编码。这是任何jQuery文件上传的核心功能。实际上是 Javascript。

55赞 mpen 2/17/2013 #9

你可以很容易地在普通的 JavaScript 中做到这一点。这是我当前项目的一个片段:

var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function(e) {
    var percent = (e.position/ e.totalSize);
    // Render a pretty progress bar
};
xhr.onreadystatechange = function(e) {
    if(this.readyState === 4) {
        // Handle file upload complete
    }
};
xhr.open('POST', '/upload', true);
xhr.setRequestHeader('X-FileName',file.name); // Pass the filename along
xhr.send(file);
28赞 farnoush resa 6/16/2013 #10

jQuery Uploadify 是我以前用来上传文件的另一个很好的插件。JavaScript 代码非常简单,如下所示:code。但是,新版本在 Internet Explorer 中不起作用。

$('#file_upload').uploadify({
    'swf': '/public/js/uploadify.swf',
    'uploader': '/Upload.ashx?formGuid=' + $('#formGuid').val(),
    'cancelImg': '/public/images/uploadify-cancel.png',
    'multi': true,
    'onQueueComplete': function (queueData) {
        // ...
    },
    'onUploadStart': function (file) {
        // ...
    }
});

我做了很多搜索,我找到了另一种解决方案,可以在没有任何插件的情况下上传文件,并且仅使用 ajax。解决方案如下:

$(document).ready(function () {
    $('#btn_Upload').live('click', AjaxFileUpload);
});

function AjaxFileUpload() {
    var fileInput = document.getElementById("#Uploader");
    var file = fileInput.files[0];
    var fd = new FormData();
    fd.append("files", file);
    var xhr = new XMLHttpRequest();
    xhr.open("POST", 'Uploader.ashx');
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
             alert('success');
        }
        else if (uploadResult == 'success')
            alert('error');
    };
    xhr.send(fd);
}
35赞 user1091949 6/26/2013 #11

Simple Ajax Uploader 是另一种选择:

https://github.com/LPology/Simple-Ajax-Uploader

  • 跨浏览器 -- 适用于 IE7+、Firefox、Chrome、Safari、Opera
  • 支持多个并发上传 -- 即使在非 HTML5 浏览器中也是如此
  • 没有闪存或外部 CSS -- 只有一个 5Kb 的 Javascript 文件
  • 可选的内置支持完全跨浏览器的进度条(使用 PHP 的 APC 扩展)
  • 灵活且高度可定制 - 使用任何元素作为上传按钮,设置您自己的进度指示器样式
  • 不需要表单,只需提供一个用作上传按钮的元素
  • MIT许可证 -- 在商业项目中免费使用

用法示例:

var uploader = new ss.SimpleUpload({
    button: $('#uploadBtn'), // upload button
    url: '/uploadhandler', // URL of server-side upload handler
    name: 'userfile', // parameter name of the uploaded file
    onSubmit: function() {
        this.setProgressBar( $('#progressBar') ); // designate elem as our progress bar
    },
    onComplete: function(file, response) {
        // do whatever after upload is finished
    }
});
12赞 Amit 5/12/2014 #12

你可以使用

$(function() {
    $("#file_upload_1").uploadify({
        height        : 30,
        swf           : '/uploadify/uploadify.swf',
        uploader      : '/uploadify/uploadify.php',
        width         : 120
    });
});

演示

16赞 ashish 6/23/2014 #13

要使用 Jquery 异步上传文件,请使用以下步骤:

第 1 步在您的项目中,打开 Nuget 管理器并添加包(jquery fileupload(只有您需要将其写入搜索框中,它才会出现并安装它。 网址:https://github.com/blueimp/jQuery-File-Upload

步骤 2在 HTML 文件中添加以下脚本,这些脚本已通过运行上述包添加到项目中:

jquery.ui.widget.js

jquery.iframe-transport.js

jquery.fileupload.js

步骤 3按照以下代码编写文件上传控制:

<input id="upload" name="upload" type="file" />

第 4 步:将 js 方法编写为 uploadFile,如下所示:

 function uploadFile(element) {
    
            $(element).fileupload({
    
                dataType: 'json',
                url: '../DocumentUpload/upload',
                autoUpload: true,
                add: function (e, data) {           
                  // write code for implementing, while selecting a file. 
                  // data represents the file data. 
                  //below code triggers the action in mvc controller
                  data.formData =
                                    {
                                     files: data.files[0]
                                    };
                  data.submit();
                },
                done: function (e, data) {          
                   // after file uploaded
                },
                progress: function (e, data) {
                    
                   // progress
                },
                fail: function (e, data) {
                    
                   //fail operation
                },
                stop: function () {
                    
                  code for cancel operation
                }
            });
        
        };

步骤 5在就绪函数中调用元素文件上传以启动该过程,如下所示:

$(document).ready(function()
{
    uploadFile($('#upload'));

});

步骤 6编写 MVC 控制器和操作,如下所示:

public class DocumentUploadController : Controller
    {       
        
        [System.Web.Mvc.HttpPost]
        public JsonResult upload(ICollection<HttpPostedFileBase> files)
        {
            bool result = false;

            if (files != null || files.Count > 0)
            {
                try
                {
                    foreach (HttpPostedFileBase file in files)
                    {
                        if (file.ContentLength == 0)
                            throw new Exception("Zero length file!");                       
                        else 
                            //code for saving a file

                    }
                }
                catch (Exception)
                {
                    result = false;
                }
            }


            return new JsonResult()
                {
                    Data=result
                };


        }

    }
10赞 tnt-rox 6/24/2014 #14

使用 |HTML5 的 readAsDataURL()一些 base64 编码器在这里摆弄小提琴

var reader = new FileReader();

        reader.onload = function(readerEvt) {
            var binaryString = readerEvt.target.result;
            document.getElementById("base64textarea").value = btoa(binaryString);
        };

        reader.readAsBinaryString(file);

然后检索:

window.open("data:application/octet-stream;base64," + base64);
46赞 ArtisticPhoenix 6/26/2014 #15

我过去做过的最简单、最健壮的方法就是简单地将隐藏的 iFrame 标签与表单一起定位 - 然后它将在 iframe 中提交,而无需重新加载页面。

也就是说,如果您不想使用插件、JavaScript 或除 HTML 之外的任何其他形式的“魔法”。当然,你可以把它与JavaScript结合起来,或者你有什么......

<form target="iframe" action="" method="post" enctype="multipart/form-data">
    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>

<iframe name="iframe" id="iframe" style="display:none" ></iframe>

您还可以读取 iframe 中服务器错误或成功响应的内容,然后将其输出给用户。onLoad

Chrome、iFrame 和 onLoad

-注意- 如果您对上传/下载时如何设置 UI 阻止程序感兴趣,您只需要继续阅读

目前,Chrome 在使用 iframe 传输文件时不会触发 iframe 的 onLoad 事件。Firefox、IE 和 Edge 都会触发文件传输的 onload 事件。

我发现唯一适用于 Chrome 的解决方案是使用 cookie。

基本上在开始上传/下载时执行此操作:

  • [客户端]开始一个时间间隔以查找 cookie 的存在
  • [服务器端]对文件数据执行任何需要操作
  • [服务器端]为客户端间隔设置 cookie
  • [客户端]Interval 看到 cookie 并像 onLoad 事件一样使用它。例如,您可以启动一个UI阻止程序,然后onLoad(或当cookie被制作时)删除UI阻止程序。

为此使用 cookie 是丑陋的,但它有效。

我制作了一个jQuery插件来处理Chrome下载时的这个问题,你可以在这里找到

https://github.com/ArtisticPhoenix/jQuery-Plugins/blob/master/iDownloader.js

同样的基本原则也适用于上传。

使用下载器(显然包括JS)

 $('body').iDownloader({
     "onComplete" : function(){
          $('#uiBlocker').css('display', 'none'); //hide ui blocker on complete
     }
 });

 $('somebuttion').click( function(){
      $('#uiBlocker').css('display', 'block'); //block the UI
      $('body').iDownloader('download', 'htttp://example.com/location/of/download');
 });

在服务器端,在传输文件数据之前,创建cookie

 setcookie('iDownloader', true, time() + 30, "/");

插件将看到 cookie,然后触发回调。onComplete

51赞 Zayn Ali 8/8/2014 #16

您只需使用 jQuery 上传即可。.ajax()

HTML格式:

<form id="upload-form">
    <div>
        <label for="file">File:</label>
        <input type="file" id="file" name="file" />
        <progress class="progress" value="0" max="100"></progress>
    </div>
    <hr />
    <input type="submit" value="Submit" />
</form>

CSS的

.progress { display: none; }

Javascript的:

$(document).ready(function(ev) {
    $("#upload-form").on('submit', (function(ev) {
        ev.preventDefault();
        $.ajax({
            xhr: function() {
                var progress = $('.progress'),
                    xhr = $.ajaxSettings.xhr();

                progress.show();

                xhr.upload.onprogress = function(ev) {
                    if (ev.lengthComputable) {
                        var percentComplete = parseInt((ev.loaded / ev.total) * 100);
                        progress.val(percentComplete);
                        if (percentComplete === 100) {
                            progress.hide().val(0);
                        }
                    }
                };

                return xhr;
            },
            url: 'upload.php',
            type: 'POST',
            data: new FormData(this),
            contentType: false,
            cache: false,
            processData: false,
            success: function(data, status, xhr) {
                // ...
            },
            error: function(xhr, status, error) {
                // ...
            }
       });
    }));
});

评论

0赞 Marco 5/18/2022
进展很好;-)
107赞 404 8/25/2014 #17

为未来的读者总结。

异步文件上传

使用 HTML5

如果支持 FormDataFile API(两者都是 HTML5 功能),则可以使用该方法使用 jQuery 上传文件。$.ajax()

您也可以在没有 FormData 的情况下发送文件,但无论哪种方式,都必须存在文件 API 才能以这样一种方式处理文件,以便可以使用 XMLHttpRequest (Ajax) 发送文件。

$.ajax({
  url: 'file/destination.html', 
  type: 'POST',
  data: new FormData($('#formWithFiles')[0]), // The form with the file inputs.
  processData: false,
  contentType: false                    // Using FormData, no need to process data.
}).done(function(){
  console.log("Success: Files sent!");
}).fail(function(){
  console.log("An error occurred, the files couldn't be sent!");
});

有关快速、纯 JavaScript(无 jQuery)示例,请参阅“使用 FormData 对象发送文件”。

后备

当不支持 HTML5(无文件 API)时,唯一的其他纯 JavaScript 解决方案(无 Flash 或任何其他浏览器插件)是隐藏的 iframe 技术,它允许在不使用 XMLHttpRequest 对象的情况下模拟异步请求。

它包括将 iframe 设置为具有文件输入的表单的目标。当用户提交请求并上传文件时,响应将显示在 iframe 中,而不是重新呈现主页。隐藏 iframe 使整个过程对用户透明,并模拟异步请求。

如果操作得当,它应该几乎可以在任何浏览器上运行,但它有一些关于如何从 iframe 获取响应的警告。

在这种情况下,您可能更喜欢使用像 Bifröst 这样的包装器插件,它使用 iframe 技术,但也提供了 jQuery Ajax 传输,允许使用如下方法发送文件$.ajax()

$.ajax({
  url: 'file/destination.html', 
  type: 'POST',
  // Set the transport to use (iframe means to use Bifröst)
  // and the expected data type (json in this case).
  dataType: 'iframe json',                                
  fileInputs: $('input[type="file"]'),  // The file inputs containing the files to send.
  data: { msg: 'Some extra data you might need.'}
}).done(function(){
  console.log("Success: Files sent!");
}).fail(function(){
  console.log("An error occurred, the files couldn't be sent!");
});

插件

Bifröst 只是一个小型包装器,它为 jQuery 的 ajax 方法添加了回退支持,但前面提到的许多插件,如 jQuery Form PluginjQuery File Upload 包括从 HTML5 到不同回退的整个堆栈,以及一些有用的功能来简化该过程。根据您的需求和要求,您可能需要考虑裸露的实现或此插件中的任何一个。

评论

0赞 Martin Zvarík 7/19/2022
Bifrost 甚至没有附加 POST 数据......强烈不推荐这个,粗略的插件,浪费时间。
8赞 Allende 7/9/2015 #18

在此处查找异步处理文件的上传过程https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications

链接中的示例

<?php
if (isset($_FILES['myFile'])) {
    // Example:
    move_uploaded_file($_FILES['myFile']['tmp_name'], "uploads/" . $_FILES['myFile']['name']);
    exit;
}
?><!DOCTYPE html>
<html>
<head>
    <title>dnd binary upload</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script type="text/javascript">
        function sendFile(file) {
            var uri = "/index.php";
            var xhr = new XMLHttpRequest();
            var fd = new FormData();

            xhr.open("POST", uri, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    // Handle response.
                    alert(xhr.responseText); // handle response.
                }
            };
            fd.append('myFile', file);
            // Initiate a multipart/form-data upload
            xhr.send(fd);
        }

        window.onload = function() {
            var dropzone = document.getElementById("dropzone");
            dropzone.ondragover = dropzone.ondragenter = function(event) {
                event.stopPropagation();
                event.preventDefault();
            }

            dropzone.ondrop = function(event) {
                event.stopPropagation();
                event.preventDefault();

                var filesArray = event.dataTransfer.files;
                for (var i=0; i<filesArray.length; i++) {
                    sendFile(filesArray[i]);
                }
            }
        }
    </script>
</head>
<body>
    <div>
        <div id="dropzone" style="margin:30px; width:500px; height:300px; border:1px dotted grey;">Drag & drop your file here...</div>
    </div>
</body>
</html>
22赞 Vivek Aasaithambi 7/28/2015 #19
var formData=new FormData();
formData.append("fieldname","value");
formData.append("image",$('[name="filename"]')[0].files[0]);

$.ajax({
    url:"page.php",
    data:formData,
    type: 'POST',
    dataType:"JSON",
    cache: false,
    contentType: false,
    processData: false,
    success:function(data){ }
});

您可以使用表单数据发布所有值,包括图像。

14赞 Erick Lanford Xenes 11/4/2015 #20

这是我的解决方案。

<form enctype="multipart/form-data">    

    <div class="form-group">
        <label class="control-label col-md-2" for="apta_Description">Description</label>
        <div class="col-md-10">
            <input class="form-control text-box single-line" id="apta_Description" name="apta_Description" type="text" value="">
        </div>
    </div>

    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>

和 JS

<script>

    $(':button').click(function () {
        var formData = new FormData($('form')[0]);
        $.ajax({
            url: '@Url.Action("Save", "Home")',  
            type: 'POST',                
            success: completeHandler,
            data: formData,
            cache: false,
            contentType: false,
            processData: false
        });
    });    

    function completeHandler() {
        alert(":)");
    }    
</script>

控制器

[HttpPost]
public ActionResult Save(string apta_Description, HttpPostedFileBase file)
{
    [...]
}
31赞 Siddhartha Chowdhury 3/31/2016 #21

这只是如何上传文件的另一种解决方案(没有任何插件)

使用简单的 JavascriptAJAX(带进度条)

HTML 部分

<form id="upload_form" enctype="multipart/form-data" method="post">
    <input type="file" name="file1" id="file1"><br>
    <input type="button" value="Upload File" onclick="uploadFile()">
    <progress id="progressBar" value="0" max="100" style="width:300px;"></progress>
    <h3 id="status"></h3>
    <p id="loaded_n_total"></p>
</form>

JS 部分

function _(el){
    return document.getElementById(el);
}
function uploadFile(){
    var file = _("file1").files[0];
    // alert(file.name+" | "+file.size+" | "+file.type);
    var formdata = new FormData();
    formdata.append("file1", file);
    var ajax = new XMLHttpRequest();
    ajax.upload.addEventListener("progress", progressHandler, false);
    ajax.addEventListener("load", completeHandler, false);
    ajax.addEventListener("error", errorHandler, false);
    ajax.addEventListener("abort", abortHandler, false);
    ajax.open("POST", "file_upload_parser.php");
    ajax.send(formdata);
}
function progressHandler(event){
    _("loaded_n_total").innerHTML = "Uploaded "+event.loaded+" bytes of "+event.total;
    var percent = (event.loaded / event.total) * 100;
    _("progressBar").value = Math.round(percent);
    _("status").innerHTML = Math.round(percent)+"% uploaded... please wait";
}
function completeHandler(event){
    _("status").innerHTML = event.target.responseText;
    _("progressBar").value = 0;
}
function errorHandler(event){
    _("status").innerHTML = "Upload Failed";
}
function abortHandler(event){
    _("status").innerHTML = "Upload Aborted";
}

PHP部分

<?php
$fileName = $_FILES["file1"]["name"]; // The file name
$fileTmpLoc = $_FILES["file1"]["tmp_name"]; // File in the PHP tmp folder
$fileType = $_FILES["file1"]["type"]; // The type of file it is
$fileSize = $_FILES["file1"]["size"]; // File size in bytes
$fileErrorMsg = $_FILES["file1"]["error"]; // 0 for false... and 1 for true
if (!$fileTmpLoc) { // if file not chosen
    echo "ERROR: Please browse for a file before clicking the upload button.";
    exit();
}
if(move_uploaded_file($fileTmpLoc, "test_uploads/$fileName")){ // assuming the directory name 'test_uploads'
    echo "$fileName upload is complete";
} else {
    echo "move_uploaded_file function failed";
}
?>

下面是示例应用程序

14赞 Daniel Nyamasyo 7/19/2016 #22

对于您的情况,您需要使用 Ajax 来方便将文件上传到服务器:

<from action="" id="formContent" method="post" enctype="multipart/form-data">
    <span>File</span>
    <input type="file" id="file" name="file" size="10"/>
    <input id="uploadbutton" type="button" value="Upload"/>
</form>

提交的数据是 formdata。在jQuery上,使用表单提交功能而不是单击按钮来提交表单文件,如下所示。

$(document).ready(function () {
   $("#formContent").submit(function(e){

     e.preventDefault();
     var formdata = new FormData(this);

 $.ajax({
     url: "ajax_upload_image.php",
     type: "POST",
     data: formdata,
     mimeTypes:"multipart/form-data",
     contentType: false,
     cache: false,
     processData: false,
     success: function(){

     alert("successfully submitted");

     });
   });
});
11赞 MEAbid 10/14/2016 #23

示例:如果您使用 jQuery,则可以轻松上传文件。这是一个小而强大的jQuery插件,http://jquery.malsup.com/form/

var $bar   = $('.ProgressBar');
$('.Form').ajaxForm({
  dataType: 'json',

  beforeSend: function(xhr) {
    var percentVal = '0%';
    $bar.width(percentVal);
  },

  uploadProgress: function(event, position, total, percentComplete) {
    var percentVal = percentComplete + '%';
    $bar.width(percentVal)
  },

  success: function(response) {
    // Response
  }
});

我希望它会有所帮助

3赞 lat94 2/21/2018 #24

这是一个老问题,但仍然没有答案正确答案,所以:

你试过jQuery-File-Upload吗?

以下是上面链接中的一个示例,可以解决您的问题:

$('#fileupload').fileupload({
    add: function (e, data) {
        var that = this;
        $.getJSON('/example/url', function (result) {
            data.formData = result; // e.g. {id: 123}
            $.blueimp.fileupload.prototype
                .options.add.call(that, e, data);
        });
    } 
});
5赞 Alireza 3/12/2018 #25

使用 HTML5JavaScript,上传异步非常容易,我与您的 html 一起创建上传逻辑,这并不完全有效,因为它需要 api,但演示它是如何工作的,如果您有从网站根目录调用的端点,此代码应该适合您:/upload

const asyncFileUpload = () => {
  const fileInput = document.getElementById("file");
  const file = fileInput.files[0];
  const uri = "/upload";
  const xhr = new XMLHttpRequest();
  xhr.upload.onprogress = e => {
    const percentage = e.loaded / e.total;
    console.log(percentage);
  };
  xhr.onreadystatechange = e => {
    if (xhr.readyState === 4 && xhr.status === 200) {
      console.log("file uploaded");
    }
  };
  xhr.open("POST", uri, true);
  xhr.setRequestHeader("X-FileName", file.name);
  xhr.send(file);
}
<form>
  <span>File</span>
  <input type="file" id="file" name="file" size="10" />
  <input onclick="asyncFileUpload()" id="upload" type="button" value="Upload" />
</form>

此外,有关 XMLHttpReques 的一些进一步信息:

XMLHttpRequest 对象

所有现代浏览器都支持 XMLHttpRequest 对象。 XMLHttpRequest 对象可用于与 Web 交换数据 服务器在幕后。这意味着可以更新 网页的一部分,而无需重新加载整个页面。


创建 XMLHttpRequest 对象

所有现代浏览器(Chrome、Firefox、 IE7+、Edge、Safari、Opera)有一个内置的 XMLHttpRequest 对象。

用于创建 XMLHttpRequest 对象的语法:

变量 = new XMLHttpRequest();


跨域访问

出于安全原因,现代浏览器不会 允许跨域访问。

这意味着它尝试加载的网页和 XML 文件, 必须位于同一台服务器上。

W3Schools 上的示例都打开了位于 W3Schools 上的 XML 文件 域。

如果您想在自己的网页上使用上面的示例,则 加载的 XML 文件必须位于您自己的服务器上。

有关更多详细信息,您可以继续阅读此处...

7赞 BlackBeard 5/21/2018 #26

您可以通过 JavaScript 使用更新Fetch API。喜欢这个:

function uploadButtonCLicked(){
    var input = document.querySelector('input[type="file"]')

    fetch('/url', {
      method: 'POST',
      body: input.files[0]
    }).then(res => res.json())   // you can do something with response
      .catch(error => console.error('Error:', error))
      .then(response => console.log('Success:', response));
}                               

优势:所有现代浏览器都原生支持 Fetch API,因此您无需导入任何内容。另外,请注意,fetch() 返回一个 Promise,然后异步使用该 Promise 进行处理。.then(..code to handle response..)

19赞 Alister 8/17/2018 #27

没有 Jquery 的现代方法是使用用户选择文件时从中返回的 FileList 对象,然后使用 Fetch 发布围绕 FormData 对象包装的 FileList<input type="file">

// The input DOM element // <input type="file">
const inputElement = document.querySelector('input[type=file]');

// Listen for a file submit from user
inputElement.addEventListener('change', () => {
    const data = new FormData();
    data.append('file', inputElement.files[0]);
    data.append('imageName', 'flower');

    // You can then post it to your server.
    // Fetch can accept an object of type FormData on its  body
    fetch('/uploadImage', {
        method: 'POST',
        body: data
    });
});
4赞 Joe Clinton 8/30/2018 #28

您可以使用JavaScript或jQuery进行异步多文件上传,而无需使用任何插件。您还可以在进度控件中显示文件上传的实时进度。我遇到了 2 个不错的链接 -

  1. ASP.NET 基于 Web 表单的多文件上传功能,带有进度条
  2. ASP.NET 在jQuery中进行的基于MVC的多文件上传

服务器端语言是 C#,但您可以进行一些修改以使其与 PHP 等其他语言一起使用。

文件上传 ASP.NET 核心 MVC:

在 HTML 中的“查看创建文件上传”控件中:

<form method="post" asp-action="Add" enctype="multipart/form-data">
    <input type="file" multiple name="mediaUpload" />
    <button type="submit">Submit</button>
</form>

现在,在控制器中创建操作方法:

[HttpPost]
public async Task<IActionResult> Add(IFormFile[] mediaUpload)
{
    //looping through all the files
    foreach (IFormFile file in mediaUpload)
    {
        //saving the files
        string path = Path.Combine(hostingEnvironment.WebRootPath, "some-folder-path"); 
        using (var stream = new FileStream(path, FileMode.Create))
        {
            await file.CopyToAsync(stream);
        }
    }
}

hostingEnvironment 变量的类型为 IHostingEnvironment,可以使用依赖注入注入到控制器中,例如:

private IHostingEnvironment hostingEnvironment;
public MediaController(IHostingEnvironment environment)
{
    hostingEnvironment = environment;
}
5赞 Supun Kavinda 10/5/2018 #29

对于 PHP,请查找 https://developer.hyvor.com/php/image-upload-ajax-php-mysql

[HTML全文]

<html>
<head>
    <title>Image Upload with AJAX, PHP and MYSQL</title>
</head>
<body>
<form onsubmit="submitForm(event);">
    <input type="file" name="image" id="image-selecter" accept="image/*">
    <input type="submit" name="submit" value="Upload Image">
</form>
<div id="uploading-text" style="display:none;">Uploading...</div>
<img id="preview">
</body>
</html>

JAVASCRIPT的

var previewImage = document.getElementById("preview"),  
    uploadingText = document.getElementById("uploading-text");

function submitForm(event) {
    // prevent default form submission
    event.preventDefault();
    uploadImage();
}

function uploadImage() {
    var imageSelecter = document.getElementById("image-selecter"),
        file = imageSelecter.files[0];
    if (!file) 
        return alert("Please select a file");
    // clear the previous image
    previewImage.removeAttribute("src");
    // show uploading text
    uploadingText.style.display = "block";
    // create form data and append the file
    var formData = new FormData();
    formData.append("image", file);
    // do the ajax part
    var ajax = new XMLHttpRequest();
    ajax.onreadystatechange = function() {
        if (this.readyState === 4 && this.status === 200) {
            var json = JSON.parse(this.responseText);
            if (!json || json.status !== true) 
                return uploadError(json.error);

            showImage(json.url);
        }
    }
    ajax.open("POST", "upload.php", true);
    ajax.send(formData); // send the form data
}

PHP的

<?php
$host = 'localhost';
$user = 'user';
$password = 'password';
$database = 'database';
$mysqli = new mysqli($host, $user, $password, $database);


 try {
    if (empty($_FILES['image'])) {
        throw new Exception('Image file is missing');
    }
    $image = $_FILES['image'];
    // check INI error
    if ($image['error'] !== 0) {
        if ($image['error'] === 1) 
            throw new Exception('Max upload size exceeded');

        throw new Exception('Image uploading error: INI Error');
    }
    // check if the file exists
    if (!file_exists($image['tmp_name']))
        throw new Exception('Image file is missing in the server');
    $maxFileSize = 2 * 10e6; // in bytes
    if ($image['size'] > $maxFileSize)
        throw new Exception('Max size limit exceeded'); 
    // check if uploaded file is an image
    $imageData = getimagesize($image['tmp_name']);
    if (!$imageData) 
        throw new Exception('Invalid image');
    $mimeType = $imageData['mime'];
    // validate mime type
    $allowedMimeTypes = ['image/jpeg', 'image/png', 'image/gif'];
    if (!in_array($mimeType, $allowedMimeTypes)) 
        throw new Exception('Only JPEG, PNG and GIFs are allowed');

    // nice! it's a valid image
    // get file extension (ex: jpg, png) not (.jpg)
    $fileExtention = strtolower(pathinfo($image['name'] ,PATHINFO_EXTENSION));
    // create random name for your image
    $fileName = round(microtime(true)) . mt_rand() . '.' . $fileExtention; // anyfilename.jpg
    // Create the path starting from DOCUMENT ROOT of your website
    $path = '/examples/image-upload/images/' . $fileName;
    // file path in the computer - where to save it 
    $destination = $_SERVER['DOCUMENT_ROOT'] . $path;

    if (!move_uploaded_file($image['tmp_name'], $destination))
        throw new Exception('Error in moving the uploaded file');

    // create the url
    $protocol = stripos($_SERVER['SERVER_PROTOCOL'],'https') === true ? 'https://' : 'http://';
    $domain = $protocol . $_SERVER['SERVER_NAME'];
    $url = $domain . $path;
    $stmt = $mysqli -> prepare('INSERT INTO image_uploads (url) VALUES (?)');
    if (
        $stmt &&
        $stmt -> bind_param('s', $url) &&
        $stmt -> execute()
    ) {
        exit(
            json_encode(
                array(
                    'status' => true,
                    'url' => $url
                )
            )
        );
    } else 
        throw new Exception('Error in saving into the database');

} catch (Exception $e) {
    exit(json_encode(
        array (
            'status' => false,
            'error' => $e -> getMessage()
        )
    ));
}
10赞 Karthik Ravichandran 11/14/2018 #30

您可以在使用 XMLHttpRequest 进行异步上传时传递其他参数和文件名(不依赖 flash 和 iframe)。将附加参数值追加到 FormData 并发送上传请求。


var formData = new FormData();
formData.append('parameter1', 'value1');
formData.append('parameter2', 'value2'); 
formData.append('file', $('input[type=file]')[0].files[0]);

$.ajax({
    url: 'post back url',
    data: formData,
// other attributes of AJAX
});

此外,Syncfusion JavaScript UI 文件上传仅使用事件参数即可为这种情况提供解决方案。您可以在此处找到文档,在此处找到有关此控件的更多详细信息,在此处输入链接说明

3赞 kvz 12/21/2018 #31

您也可以考虑使用类似 https://uppy.io 的东西。

它可以在不离开页面的情况下上传文件,并提供一些奖励,例如拖放,在浏览器崩溃/网络不稳定的情况下恢复上传,以及从Instagram等导入。 它是开源的,不依赖于 jQuery/React/Angular/Vue,但可以与之一起使用。免责声明:作为它的创造者,我有偏见;)

-5赞 Wisken Whited 4/8/2019 #32

您可以使用以下代码。

async: false(true)

评论

0赞 kabirbaidhya 9/14/2020
你能详细说明你的答案吗?目前尚不清楚在哪里进行此更改。
0赞 Wisken Whited 9/16/2020
你可以在ajax调用函数上添加它
1赞 Sebastian Simon 3/5/2021
这是无效的语法,不能回答这个问题。
4赞 Kamil Kiełczewski 7/5/2019 #33

尝试

async function saveFile() 
{
    let formData = new FormData();           
    formData.append("file", file.files[0]);
    await fetch('addFile.do', {method: "POST", body: formData});    
    alert("Data Uploaded: ");
}
<span>File</span>
<input type="file" id="file" name="file" size="10"/>
<input type="button" value="Upload" onclick="saveFile()"/>

由浏览器自动设置,文件名也自动添加到FormData参数中(服务器可以轻松读取)。这是使用 err 处理和 json 添加的更发达的示例content-type='multipart/form-data'filename

async function saveFile(inp) 
{
    let user = { name:'john', age:34 };
    let formData = new FormData();
    let photo = inp.files[0];      
         
    formData.append("photo", photo);
    formData.append("user", JSON.stringify(user));  
    
    try {
       let r = await fetch('/upload/image', {method: "POST", body: formData}); 
       console.log('HTTP response code:',r.status); 
       alert('success');
    } catch(e) {
       console.log('Huston we have problem...:', e);
    }
    
}
<input type="file" onchange="saveFile(this)" >
<br><br>
Before selecting the file Open chrome console > network tab to see the request details.
<br><br>
<small>Because in this example we send request to https://stacksnippets.net/upload/image the response code will be 404 ofcourse...</small>

2赞 Diego Vinícius 2/28/2020 #34

如果使用 promise which ajax 并检查文件是否有效并保存在您的后端中,这样您就可以在用户浏览您的页面时在前面使用一些动画。

您甚至可以使用递归方法使其平行上传或堆叠