如何异步上传文件?


2914

我想用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"/>

我只获取文件名,而不是上传文件。我该怎么做才能解决此问题?


关于jQuery的文件上传,有各种现成的插件。进行这种上载的技巧并不是一件令人愉快的事情,因此人们喜欢使用现成的解决方案。这里有几个: - JQuery的文件上传 - 多文件上传插件 - 迷你多文件上传 - jQuery的文件上传你可以搜索更多的项目上NPM(使用“jQuery的插件”作为关键字),或在Github。
令人愉快的

72
您只得到文件名是因为您的var文件名得到的是$('#file')的值,而不是输入中的文件
Jimmy

21
这是一个很好的例子http ://blueimp.github.io/jQuery-File-Upload/-HTML5 ajax上传-不支持的浏览器向iframe的优美回退-多文件异步上传我们已经使用了它,并且效果很好。(此处的文档
Ashish Panery

3
还要检查一下:stackoverflow.com/questions/6974684/…,这里说明了如何通过jQuery实现它
Chococroc 2014年

2
@Jimmy他将如何获取位于输入中的文件呢?
alex 2014年

Answers:


2519

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

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组件并非在每种浏览器中都可用。


14
然后可以在upload.php中使用$ _FILES吗?
亚历山德罗·科森蒂诺

71
这应该在Internet Explorer中有效,但仅在版本10中有效。(caniuse.com/xhr2
Tyler

18
嗨,我很欣赏PHP是您选择的语言...但是我想知道您是否知道这是否也可以在ASP.NET MVC中使用?我是.NET开发人员,因此我尝试利用您的简单示例来上传一些AJAX文件,但在服务器端却找不到通过AJAX发布的文件。我正在使用最新的Chrome。
Shumii

25
这是FORMDATA谁在这里做所有的魔法。请务必检查这些文档-它涵盖了有关多个文件和字段的所有问题。
化身

4
只是这样,其他人就不会花费数小时的时间... 如果您要在PHP中(可能还有其他地方)使用数据,那么这name="file"<input>文件标签上非常重要。我使用javascript动态创建了一个表单,因此我不需要name属性,但是发现了您绝对需要它来检索数据服务器端的困难方式。
基瓦克·沃尔夫

273

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

使用“新” HTML5 fileAPI 需了解的重要一点是,直到IE 10才支持它。如果您要针对的特定市场对旧版本Windows的倾向高于平均水平,则可能无法使用它。

截至2017年,大约5%的浏览器是IE 6、7、8或9之一。如果您进入一家大公司(例如,这是B2B工具,或者您要提供培训的内容),那么这个数字可能会飙升。2016年,我与一家使用IE8的公司进行了交易,这些公司的机器中有60%以上使用IE8。

截至本次编辑的2019年,距离我最初的回答差不多11年了。IE9及更低版本在全球范围内均在1%左右,但仍存在使用率更高的集群。

无论功能如何,重要的收获是,请检查您的浏览器用户使用。如果不这样做,您将学到一个快速而痛苦的课程,以了解为什么“为我工作”在交付给客户的产品中不够好。caniuse是一个有用的工具,但请注意他们从哪里获得人口统计信息。它们可能与您的不一致。这从未比企业环境更真实。

我在2008年的回答如下。


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

这是一个“真实”的帖子,因此并不完全是交互式的。如果您需要状态,则需要服务器端进行处理。具体取决于您的服务器。ASP.NET具有更好的机制。PHP Plain失败了,但是您可以使用Perl或Apache修改来解决它。

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

或使用Java / Flash解决方案。他们可以更灵活地处理自己的帖子...


142
根据记录,现在有可能做到纯AJAX文件上传浏览器是否支持文件API - developer.mozilla.org/en/using_files_from_web_applications
meleyal

iframe解决方案非常简单且易于使用
Matthew Lock

IE早在IE7之前就一直支持XHR,而早在IE5上就通过ActiveX支持XHR。w3schools.com/ajax/ajax_xmlhttprequest_create.asp。这样做的实际方法肯定是针对Flash(shockwave)组件,或推出Flash / ActiveX(Silverlight)控件。如果您可以通过javascript发出请求并处理响应,则它是ajax ..虽然如此,但ajax是xhr的同义词,但它本身并未描述提供/交换有效负载的下划线机制/组件。
Brett Caswell 2015年

4
@BrettCaswell我并不是说不可能使用AJAX / XHR,只是无法将与之相关的文件发布到旧的但永生的IE版本上。那是过去并且仍然是完全正确的。
奥利2015年

这不是方法,这是用户体验意见-也许是有效的。
Nimjox

112

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

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

它使用JSON-因此对于PHP旧版本将无法使用。
洛伦佐·马努奇

似乎比Ajax File Upload干净得多,在Ajax File Upload中,为了使用该死的东西,我需要包含大量代码。
ripper234 2011年


35
“此插件是在GNU GPL 2或更高版本以及GNU LGPL 2或更高版本下开源的。” 因此,只要您不分发副本或修改版本,就不必打开项目。
Trantor Liu

我想念什么吗?该库似乎不再使用jquery,因此它不支持答案中的语法?
詹姆斯·麦考马克

102

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


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


1
是的,您可以发布到iframe并在其中捕获文件。我对此的经验非常有限,因此我无法对此发表评论。
马蒂亚斯(Mattias)

15
小提示:在最新版本的chrome和firefox中,有可能,stackoverflow.com
questions/4856917/…

IE9及以下版本不支持
辐射

96

为将来的读者做准备。

异步文件上传

使用HTML5

您可以使用jQuery上传文件使用FormDataFile API$.ajax()方法(两种HTML5功能),。

您也可以发送文件 不带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(无File 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到不同后备的整个堆栈,以及一些简化该过程的有用功能。根据您的需求和要求,您可能需要考虑一个简单的实现或两个插件之一。


3
根据文档要注意的一件事:您还应该发送contentType: false。当我不发送带有chrome的表单时,jQuery禁用了表单内容类型。

好答案。有一些改进建议:删除与答案无关的代码部分,例如.done().fail()回调。同样,一个不使用FormData和赞成/反对的列表的示例也很棒。
2015年

我收到此错误:TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement.
Candlejack

85

这个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');
  }
});

1
@ user840250 jQuery 1.9.1吗?
Jordan Feldstein 2013年

62

我一直在使用下面的脚本上传图像,但效果很好。

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


5
-1用于使用jQuery,而不使用其选择器引擎和事件处理程序。addEventListener不是跨浏览器。
2013年

3
因为添加一个单独的答案将毫无意义,该答案主要基于此答案,而仅需进行一些更改。而是,应纠正此答案。
2013年

2
@RainFromHeaven,请,您可以编辑答案吗?我不知道如何以跨浏览器的方式进行操作。
Thiago Negri 2014年

2
仍无法在IE 9及更低版本中使用。用户分配仍使用那些版本的IE。
皮埃尔·

1
有人可以解释一下如何使它在asp.net中工作吗?我使用webmethod吗?如果是,它将是什么样?
2015年

49

您可以非常轻松地在原始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);

3
@加里:对不起,我也应该发布那一点。我只是在HTML5中使用新的拖放功能。您可以在此处找到示例:html5demos.com/file-api#view-source-只需单击“查看源代码”。本质上,ondrop您可以在活动中进行var file = e.dataTransfer.files[0]
mpen 2013年

也许此后该问题已被编辑,但是在我打开的一个讨论中,一些人认为如果OP请求使用jQuery解决方案(如果存在),那么普通的JS回答就不可行了,并且此类回答属于一个单独的问题。
安迪

4
@Andy好吧,我不同意,似乎还有34个人也这样做。如果可以使用jQuery,那么当然可以使用JavaScript。无论如何,这是一个社区网站-我想在这里帮助的不仅仅是OP。每个人都可以自由选择/使用他们最喜欢的答案。有些人只是偏向于jQuery,因为他们认为这样做会简化/减少代码行,而实际上他们根本不需要额外的库。
mpen

47

您可以使用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) {
                // ...
            }
       });
    }));
});

1
@RaydenBlack仅jQuery。
Zayn Ali 2015年

如何获得上传进度?
阿里·谢拉菲特

44

我过去做过的最简单,最可靠的方法是,仅将表单指向一个隐藏的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的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回调。


3
我喜欢它。如果只有谁能提及这种出色解决方案的潜在问题。我真的不明白为什么人们会在解决方案时选择使用这些笨拙的库和插件。
Yevgeniy Afanasyev

1
好吧,我想原因是在上传时会显示一些进度信息。
Prakhar Mishra

32

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


1
我对此答案感兴趣,您有可以链接的演示吗?
lfender6445

32

我已经在Rails环境中编写了这个。如果您使用轻量级的jQuery-form插件,则仅包含五行JavaScript。

挑战在于如何使AJAX上传成为标准 remote_form_for无法理解多部分表单提交。它不会发送Rails随AJAX请求返回的文件数据。

这就是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上使用它,它的工作原理像冠军。


31

Simple Ajax Uploader是另一个选择:

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

  • 跨浏览器-适用于IE7 +,Firefox,Chrome,Safari,Opera
  • 支持多个并发上传-即使在非HTML5浏览器中
  • 无需Flash或外部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
    }
});

2
到目前为止,这似乎是最有希望的,您吸引了我IE7+!现在尝试一下。谢谢
Pierre

25

jQuery Uploadify是另一个好插件,我之前曾使用过该插件来上传文件。JavaScript代码很简单,如下所示:代码。但是,新版本在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);
}

2
Uploadify已经死亡多年。不再受支持或维护。
Ray Nicholus

24

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

使用简单的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";
}
?>

这是示例应用程序


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){ }
});

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


6
注意:由于从不缓存cache: false,因此在POST请求上是多余的。POST
Gone Coding

@Vivek Aasaithambi,我收到此错误:TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement.
Candlejack

15

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

步骤1在您的项目中,打开Nuget管理器并添加包(jquery fileupload(仅需要在搜索框中编写它,它就会出现并安装它。))URL:https : //github.com/blueimp/jQuery-File-上载

步骤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
                };


        }

    }

14

没有Jquery的现代方法是使用用户选择文件时从中获得的FileList对象<input type="file">,然后使用Fetch发布包裹在FormData对象周围的FileList 。

// 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
    });
});

显然不支持IE
Marco Demaio

11

您可以在此处看到带有有效演示的解决方案,可以预览表单文件并将其提交到服务器。对于您的情况,您需要使用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>

提交的数据是一个表单数据。在您的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

示例:如果使用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
  }
});

我希望这会有所帮助


10

您可以使用

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

演示版


9

|使用HTML5的readAsDataURL()某些base64编码器将文件转换为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);

9

在使用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文件上传仅使用事件参数即可为该方案提供解决方案。你可以找到的文档在这里和有关此控件的详细信息在这里输入链接的描述在这里


8

在此处查找异步处理文件的上传过程https : //developer.mozilla.org/zh-CN/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>

7

这是我的解决方案。

<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)
{
    [...]
}

2
您似乎在答案中混入了某种框架。您至少应提及您的答案适用于哪种框架。更好的是,删除所有框架内容,仅提出所提出问题的答案。
Zero3,2015年

2
所以实际上有一个名为“ mvc”的mvc框架?它使用了csharpish语法?太残酷了
nonchip

6

使用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对象的语法:

变量=新的XMLHttpRequest();


跨域访问

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

这意味着该网页及其尝试加载的XML文件必须位于同一服务器上。

W3Schools上的示例位于W3Schools域上的所有打开的XML文件。

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

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


5

您可以通过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,然后通过使用.then(..code to handle response..)异步处理该Promise


4

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

  1. 具有进度条的基于ASP.NET Web窗体的多文件上传功能
  2. jQuery中基于ASP.NET MVC的多文件上传

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

文件上传ASP.NET Core 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;
}

您能否在答案中包含解决方案的实质,否则,如果链接的网站发生更改或脱机,该解决方案将变得毫无用处。
迪马·科热文

4

对于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()
        )
    ));
}

4

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

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


上面的链接已死。这是github:github.com/transloadit/uppy
克里斯·查尔斯

uppy.io是否支持CloudFlare + GitHub页面,对我来说呢?仍然具有直接回购链接仍然有用:)
kvz19年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.