JavaScript/jQuery 使用 JSON 数据通过 POST 下载文件 [英] JavaScript/jQuery to download file via POST with JSON data

查看:123
本文介绍了JavaScript/jQuery 使用 JSON 数据通过 POST 下载文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基于 jquery 的单页 web 应用程序.它通过 AJAX 调用与 RESTful Web 服务进行通信.

I have a jquery-based single-page webapp. It communicates with a RESTful web service via AJAX calls.

我正在努力完成以下工作:

I'm trying to accomplish the following:

  1. 将包含 JSON 数据的 POST 提交到 REST 网址.
  2. 如果请求指定了 JSON 响应,则返回 JSON.
  3. 如果请求指定了 PDF/XLS/etc 响应,则返回可下载的二进制文件.

我有 1 &2 现在工作,客户端 jquery 应用程序通过基于 JSON 数据创建 DOM 元素在网页中显示返回的数据.从 Web 服务的角度来看,我还有 #3 工作,这意味着如果给定正确的 JSON 参数,它将创建并返回一个二进制文件.但我不确定在客户端 javascript 代码中处理 #3 的最佳方法.

I have 1 & 2 working now, and the client jquery app displays the returned data in the web page by creating DOM elements based on the JSON data. I also have #3 working from the web-service point of view, meaning it will create and return a binary file if given the correct JSON parameters. But I'm unsure the best way to deal with #3 in the client javascript code.

是否可以从这样的 ajax 调用中取回可下载的文件?如何让浏览器下载并保存文件?

Is it possible to get a downloadable file back from an ajax call like this? How do I get the browser to download and save the file?

$.ajax({
    type: "POST",
    url: "/services/test",
    contentType: "application/json",
    data: JSON.stringify({category: 42, sort: 3, type: "pdf"}),
    dataType: "json",
    success: function(json, status){
        if (status != "success") {
            log("Error loading data");
            return;
        }
        log("Data loaded!");
    },
    error: function(result, status, err) {
        log("Error loading data");
        return;
    }
});

服务器使用以下标头进行响应:

The server responds with the following headers:

Content-Disposition:attachment; filename=export-1282022272283.pdf
Content-Length:5120
Content-Type:application/pdf
Server:Jetty(6.1.11)

另一个想法是生成 PDF 并将其存储在服务器上,然后返回包含文件 URL 的 JSON.然后,在 ajax 成功处理程序中发出另一个调用以执行如下操作:

Another idea is to generate the PDF and store it on the server and return JSON that includes a URL to the file. Then, issue another call in the ajax success handler to do something like the following:

success: function(json,status) {
    window.location.href = json.url;
}

但是这样做意味着我需要多次调用服务器,并且我的服务器需要构建可下载的文件,将它们存储在某处,然后定期清理该存储区域.

But doing that means I would need to make more than one call to the server, and my server would need to build downloadable files, store them somewhere, then periodically clean up that storage area.

必须有一种更简单的方法来实现这一点.想法?

There must be a simpler way to accomplish this. Ideas?

在查看了 $.ajax 的文档后,我发现响应 dataType 只能是 xml、html、script、json、jsonp、text 之一,所以我猜在那里无法使用 ajax 请求直接下载文件,除非我按照@VinayC 回答中的建议使用数据 URI 方案嵌入二进制文件(这不是我想做的事情).

After reviewing the docs for $.ajax, I see that the response dataType can only be one of xml, html, script, json, jsonp, text, so I'm guessing there is no way to directly download a file using an ajax request, unless I embed the binary file in using Data URI scheme as suggested in the @VinayC answer (which is not something I want to do).

所以我想我的选择是:

  1. 不要使用 ajax,而是提交表单帖子并将我的 JSON 数据嵌入到表单值中.可能需要处理隐藏的 iframe 等.

  1. Not use ajax and instead submit a form post and embed my JSON data into the form values. Would probably need to mess with hidden iframes and such.

不要使用 ajax,而是将我的 JSON 数据转换为查询字符串以构建标准 GET 请求并将 window.location.href 设置为此 URL.可能需要在我的点击处理程序中使用 event.preventDefault() 以防止浏览器更改应用程序 URL.

Not use ajax and instead convert my JSON data into a query string to build a standard GET request and set window.location.href to this URL. May need to use event.preventDefault() in my click handler to keep browser from changing from the application URL.

使用我上面的其他想法,但通过@naikus 答案中的建议进行了增强.使用一些参数提交 AJAX 请求,让 Web 服务知道这是通过 ajax 调用调用的.如果 Web 服务是从 ajax 调用中调用的,只需将带有 URL 的 JSON 返回到生成的资源.如果直接调用资源,则返回实际的二进制文件.

Use my other idea above, but enhanced with suggestions from the @naikus answer. Submit AJAX request with some parameter that lets web-service know this is being called via an ajax call. If the web service is called from an ajax call, simply return JSON with a URL to the generated resource. If the resource is called directly, then return the actual binary file.

我越想越喜欢最后一个选项.通过这种方式,我可以获取有关请求的信息(生成时间、文件大小、错误消息等),并且可以在开始下载之前根据该信息采取行动.缺点是服务器上的额外文件管理.

The more I think about it, the more I like the last option. This way I can get information back about the request (time to generate, size of file, error messages, etc.) and I can act on that information before starting the download. The downside is extra file management on the server.

还有其他方法可以做到这一点吗?我应该注意这些方法的任何优点/缺点?

Any other ways to accomplish this? Any pros/cons to these methods I should be aware of?

推荐答案

letronje 的解决方案仅适用于非常简单的页面.document.body.innerHTML += 获取正文的 HTML 文本,附加 iframe HTML,并将页面的 innerHTML 设置为该字符串.这将消除您的页面具有的任何事件绑定等.创建一个元素并使用 appendChild 代替.

letronje's solution only works for very simple pages. document.body.innerHTML += takes the HTML text of the body, appends the iframe HTML, and sets the innerHTML of the page to that string. This will wipe out any event bindings your page has, amongst other things. Create an element and use appendChild instead.

$.post('/create_binary_file.php', postData, function(retData) {
  var iframe = document.createElement("iframe");
  iframe.setAttribute("src", retData.url);
  iframe.setAttribute("style", "display: none");
  document.body.appendChild(iframe);
}); 

或者使用 jQuery

Or using jQuery

$.post('/create_binary_file.php', postData, function(retData) {
  $("body").append("<iframe src='" + retData.url+ "' style='display: none;' ></iframe>");
}); 

这实际上是做什么的:使用变量 postData 中的数据向/create_binary_file.php 执行发布;如果该帖子成功完成,请在页面正文中添加一个新的 iframe.假设来自/create_binary_file.php 的响应将包含一个值url",即可以从中下载生成的 PDF/XLS/etc 文件的 URL.向引用该 URL 的页面添加 iframe 将导致浏览器促使用户下载文件,假设 Web 服务器具有适当的 MIME 类型配置.

What this actually does: perform a post to /create_binary_file.php with the data in the variable postData; if that post completes successfully, add a new iframe to the body of the page. The assumption is that the response from /create_binary_file.php will include a value 'url', which is the URL that the generated PDF/XLS/etc file can be downloaded from. Adding an iframe to the page that references that URL will result in the browser promoting the user to download the file, assuming that the web server has the appropriate mime type configuration.

这篇关于JavaScript/jQuery 使用 JSON 数据通过 POST 下载文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆