javascript 如何让浏览器提示用户保存服务器动态生成的文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20714631/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 19:05:12  来源:igfitidea点击:

How do I get browser to prompt user to save a file dynamically generated by server?

javascriptajaxfilebrowsersave

提问by RPW

Clients submit post requests using jquery ajax as illustrated below:

客户端使用 jquery ajax 提交 post 请求,如下图所示:

$.ajax({
    url: "/xxx?request1", 
    data: theParams,
    type: 'post',
    error: function(XMLHttpRequest, textStatus, errorThrown){
        // error handling
    },
    success: function(data){
    var theResult = JSON.parse(data);
        // success handling
    }
});

Apache is configured to pass requests with /xxx?to a custom app. The app processes the request and returns information. Usually, this information returned as JSoN and is displayed in the "success handling" section, using jquery/javascript. The app writes the following headers (which are then returned via apache) prior to writing the JSON:

Apache 配置为将请求传递/xxx?给自定义应用程序。应用程序处理请求并返回信息。通常,此信息作为 JSoN 返回,并使用 jquery/javascript 显示在“成功处理”部分中。该应用程序在写入 JSON 之前写入以下标头(然后通过 apache 返回):

HTTP/1.0 200 OK
Connection: close
Server: MyServer v. 0.826
Content-Type: text/html

I also have cookies working by placing the following right after the 200 OK line:

我还通过在 200 OK 行之后放置以下内容来使 cookie 工作:

Set-Cookie: cookie_name=value; Domain=example.com; Path=/; Expires=Fri, 21-Mar-2014 01:40:22 GMT; HttpOnly

In one scenario, I'd like the user to be able to save the returned data (as a plain text file). But here is where I run into problems.

在一种情况下,我希望用户能够保存返回的数据(作为纯文本文件)。但这是我遇到问题的地方。

If I use JavaScript to open a window and write the data to the new window, I've found that Safari and Chrome both disable the "Save as..." menu option (on Macs).

如果我使用 JavaScript 打开一个窗口并将数据写入新窗口,我发现 Safari 和 Chrome 都禁用了“另存为...”菜单选项(在 Mac 上)。

(I have got a version working by using base64 URI, but that looks unpolished relative to the rest of the site.)

(我有一个使用 base64 URI 的版本,但相对于站点的其余部分,它看起来很粗糙。)

I then began trying to include a Content-Disposition: attachment; filename=file.txt header but I could never get the browser to produce a prompt. I tried placing this header right after the 200 OK line, as well as later:

然后我开始尝试包含一个Content-Disposition: attachment; filename=file.txt 标题,但我永远无法让浏览器产生提示。我尝试将这个标题放在 200 OK 行之后,以及稍后:

Content-Type: text/plain
Content-Disposition: attachment; filename=file.txt

In addition to being not sure of the exact format of the Content-Dispositionheader, I'm also not sure if I have the Content-Typecorrect or if there's something in the ajax handler code that is preventing the save.

除了不确定Content-Disposition标头的确切格式之外,我也不确定我是否有Content-Type正确的或 ajax 处理程序代码中是否有阻止保存的内容。

I've tried to find examples where everything is put together, but can only find parts and clearly I can't get it put together correctly. Any suggestions?

我试图找到所有东西都放在一起的例子,但只能找到部分,显然我无法正确地将它们放在一起。有什么建议?

I'm targeting only modern browsers, three major platforms (Mac/Windows/Linux), and only HTML5/JavaScript on the client side.

我只针对现代浏览器、三个主要平台(Mac/Windows/Linux)和客户端的 HTML5/JavaScript。

回答by 1ace

Content-Disposition: attachmentis the right header, but the browser only obeys it when loading the file directly. Using AJAX (even through jQuery) will not work.

Content-Disposition: attachment是正确的标题,但浏览器仅在直接加载文件时才遵守它。使用 AJAX(甚至通过 jQuery)将不起作用。

There is a way to do this. Read the full explanation in this answer, but basically you just have to write that in your successfunction:

有一种方法可以做到这一点。阅读这个答案中的完整解释,但基本上你只需要在你的success函数中写下它:

window.location = "data:application/octet-stream," + encodeURIComponent(theResult);

Edit:FileSaver.jsprovides a wrapper improving browser compatibilityand adding support for filenames for compatible browsers:

编辑:FileSaver.js提供了一个改进浏览器兼容性的包装,并为兼容浏览器添加了对文件名的支持:

var blob = new Blob(["Hello, world!"], {type: "text/plain;charset=utf-8"});
saveAs(blob, "hello world.txt");