为什么没有办法使用ajax请求下载文件?

时间:2013-02-04 08:01:41

标签: javascript ajax post download

在我们的应用程序中,我们需要实现以下场景:

  1. 从客户端发送请求
  2. 服务器处理请求并生成文件
  3. 服务器返回响应文件
  4. 客户端浏览器显示文件下载弹出对话框,允许用户下载文件
  5. 我们的应用程序是基于ajax的应用程序,因此我们发送ajax请求(如使用jquery.ajax()函数)非常简单方便。

    但是在googilng之后,事实证明只有在使用非ajax POST请求时才能进行文件下载(如this popular SO thread中所述)。因此,我们需要实现更加丑陋且更复杂的解决方案,这需要使用嵌套隐藏字段构建form的HTML结构。

    有人可以用简单的话来解释为什么ajax请求不能用于下载文件?那背后的机制是什么?

4 个答案:

答案 0 :(得分:58)

它与AJAX无关。当然,您可以使用AJAX下载文件。但是,该文件将保留在内存中,即您无法将文件保存到磁盘。这是因为JavaScript无法与磁盘进行交互。这将是一个严重的安全问题,并且在所有主流浏览器中都被阻止。

答案 1 :(得分:3)

这可以使用名为Blob的新HTML5功能来完成。有一个库FileSaver.js可以用作该功能之上的包装器。

答案 2 :(得分:1)

这是我两天前问自己的问题。有一个项目使用ExtJS编写客户端,服务器端实现在ASP.Net上。我必须将服务器端转换为Java。有一个下载XML文件的功能,该服务器在客户端发出Ajax请求后生成。我们都知道,在Ajax请求之后下载文件是不可能的,只是将其存储在内存中。但是......在原始应用程序浏览器中显示通常的对话框,打开,保存和取消下载选项。 ASP.Net以某种方式改变了标准行为......我需要两天才能再次证明 - 没有办法按常规方式下载文件...唯一的例外是ASP.Net ......这里是ASP.Net代码

public static void WriteFileToResponse(byte[] fileData, string fileName)
    {
        var response = HttpContext.Current.Response;

        var returnFilename = Path.GetFileName(fileName);
        var headerValue = String.Format("attachment; filename={0}", 
            HttpUtility.UrlPathEncode(
                String.IsNullOrEmpty(returnFilename) 
                    ? "attachment" : returnFilename));
        response.AddHeader("content-disposition", headerValue);
        response.ContentType = "application/octet-stream";
        response.AddHeader("Pragma", "public");

        var utf8 = Encoding.UTF8;
        response.Charset = utf8.HeaderName;
        response.ContentEncoding = utf8;
        response.Flush();
        response.BinaryWrite(fileData);
        response.Flush();
        response.Close();
    }

此方法是从WebMethod调用的,而后者则是从ExtJS.Ajax.request调用的。那是魔术。对我来说,我已经以servlet和隐藏的iframe结束了......

答案 3 :(得分:-3)

您可以通过在下载页面中使用隐藏的iframe来完成此操作

只需在ajax成功响应中设置隐藏iframe的src即可完成任务...

  $.ajax({
        type: 'GET',
        url: './page.php',
        data: $("#myform").serialize(),
        success: function (data) {
          $("#middle").attr('src','url');
        },

});