【问题标题】:Why threre is no way to download file using ajax request?为什么无法使用 ajax 请求下载文件?
【发布时间】:2013-01-18 21:44:03
【问题描述】:

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

  1. 客户端发送请求
  2. 服务器处理请求并生成文件
  3. 服务器返回文件作为响应
  4. 客户端浏览器显示文件下载弹出对话框并允许用户下载文件

我们的应用程序是基于 ajax 的应用程序,因此我们发送 ajax 请求将非常简单方便(例如使用 jquery.ajax() 函数)。

但是在 googilng 之后,发现只有在使用非 ajax POST 请求时才可以下载文件(如this popular SO thread 中所述)。所以我们需要实现更丑更复杂的解决方案,需要构建带有嵌套隐藏字段的form的HTML结构。

谁能用简单的话解释一下为什么不能使用ajax请求来下载文件?这背后的机制是什么?

【问题讨论】:

标签: javascript ajax post download


【解决方案1】:

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

【讨论】:

  • 这似乎不正确,因为您可以使用 Blob 来保存文件,例如这里:stackoverflow.com/questions/19327749/…,这似乎不是一个安全问题,因为它不是直接交互,只是告诉浏览器从内存而不是服务器下载文件。
  • 它与window.location = urlWhereFileCanBeDownloaded 有什么不同,window.location = urlWhereFileCanBeDownloaded 无论如何都提供文件,从而允许 JS 绕过所有这些?
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    这也是我两天前问自己的同一个问题。有一个项目,客户端使用 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 调用的,而 WebMethod 又是从 ExtJS.Ajax.request 调用的。这就是魔法。对我来说是什么,我以 servlet 和隐藏的 iframe 结束...

    【讨论】:

      【解决方案4】:

      您可以通过在下载页面中使用隐藏的 iframe 来做到这一点

      只需在您的 ajax 成功响应中设置隐藏 iframe 的 src,您的任务就完成了...

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

      【讨论】:

        猜你喜欢
        • 2021-12-06
        • 2014-01-16
        • 1970-01-01
        相关资源
        最近更新 更多