我想用jQuery异步上传文件。

$(文档).ready(函数(){$(“#uploadbutton”).click(函数(){var filename=$(“#file”).val();$.ajax美元({类型:“POST”,url:“addFile.do”,enctype:'多部分/表单数据',数据:{文件:文件名},成功:函数(){alert(“上传的数据:”);}});});});<script src=“https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js“></script><span>文件</span><input type=“file”id=“file”name=“file”size=“10”/><input id=“uploadbutton”type=“button”value=“Upload”/>

我只得到文件名,而不是上传文件。我可以做什么来解决这个问题?


当前回答

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

带有进度条的基于ASP.NET Web表单的多文件上载功能jQuery中基于ASP.NET MVC的多文件上载

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

文件上载ASP.NET核心MVC:

在html中的View create file upload控件中:

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

其他回答

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


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

为未来读者整理。

异步文件上载

使用HTML5

如果支持FormData和File API(这两个HTML5功能),则可以使用$.ajax()方法使用jQuery上载文件。

您也可以在不使用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技术,但也提供jQueryAjax传输,允许仅使用$.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表单插件或jQuery文件上载,都包括从HTML5到不同回退的整个堆栈,以及一些有用的功能来简化过程。根据您的需要和要求,您可能需要考虑一个简单的实现或其中一个插件。

我过去做过的最简单、最健壮的方法是,简单地将表单中隐藏的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、iFrames和onLoad

-注意-如果你对上传/下载时如何设置UI拦截器感兴趣,你只需要继续阅读

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

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

要基本上在开始上传/下载时做到这一点:

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

用饼干做这件事很难看,但它很管用。

我制作了一个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回调。

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

使用“新”HTML5文件API需要了解的一件重要事情是,直到IE 10才支持它。如果你所瞄准的特定市场对旧版本Windows的倾向高于平均水平,你可能无法访问它。

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

截至本期编辑时,已是2019年,距离我最初的答案已经过去了11年。IE9和IE9的全球使用率在1%左右,但仍有使用率较高的集群。

无论有什么功能,重要的一点是检查用户使用的浏览器。如果你不这样做,你会很快学到一个痛苦的教训,为什么“为我工作”在交付给客户时不够好。犬科动物是一种有用的工具,但请注意它们的人口统计数据来源。它们可能与您的不一致。这比企业环境更真实。

我2008年的回答如下。


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

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

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

或者使用Java/Flash解决方案。他们在处理自己的帖子时更加灵活。。。

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

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