在 Javascript 中,如何在窗口位置重定向 Ajax 响应

Posted

技术标签:

【中文标题】在 Javascript 中,如何在窗口位置重定向 Ajax 响应【英文标题】:In Javascript how can I redirect an Ajax response in window location 【发布时间】:2016-12-04 14:12:18 【问题描述】:

我目前有以下 工作 代码(角度但适用于任何 JS 框架):

var url = '/endpoint/to/my/file';

$http(
  method: 'GET',
  url: url
)
.success(function(jdata) 
  window.location = url;
)
.error(function(je)
  // display errors on page
);

上面是在表单完成并且用户点击“提交”之后调用的(实际情况比这要复杂一些,但想法是一样的)。我异步进行表单检查,所以没有页面重新加载。

如果请求成功,返回一个二进制文件(一个pdf文件),如果不成功,请求返回一个400 BadRequest,错误格式为JS。所以我要做的是,如果成功,我会重定向到相同的 url 以获取 PDF,否则我会得到 JSON 错误对象并对其进行处理。

如果请求成功,我如何避免发出两个请求?

注意 1:在后端我想只保留一个可以完成所有任务的路由,检查 + 返回 PDF 注意2:在我看来,目前的情况非常好,因为我有一个异步表单检查,如果成功,文件会直接在浏览器中下载,因为我在成功响应的 HTTP 标头中有"CONTENT-DISPOSITION" -> "attachment"

更新:Emile 要求的有关架构的其他信息: 在我的用例中,我有一个端点来检查输入(和其他外部要求)。出于安全原因,如果不满足所有要求,我将无法输出 PDF,因此无论如何我必须在交付文件之前进行检查(文件是自动生成的)。因此,拥有两个端点只是多余的,并增加了一些不必要的复杂性。

在编写时,我认为另一种解决方案可能是在进行检查时在端点上传递一个参数,这样如果成功,它就会停止并且不生成 PDF,然后重定向到没有标志的同一个端点输出PDF。 所以我做了两次检查,但只加载(并生成 - 这是资源密集型的)文件一次,我只有一个端点......

这是修改后的代码:

var url = '/endpoint/to/my/file';

$http(
  method: 'GET',
  url: url+'?check'
)
.success(function(jdata) 
  window.location = url;
)
.error(function(je)
  // display errors on page
);

在后端(我使用 Play 框架/Scala)

def myendpoint(onlyDoCheck: Boolean = false) = Actionimplicit request =>
   myForm.bindFromRequest.fold(
     e => BadRequest(myErrors),
     v => if(onlyDoCheck) Ok(simpleOkResponse) else  Ok(doComputationgeneratefileandoutputfile)
   )

【问题讨论】:

你见过吗:***.com/questions/20830309/… url 在对象闭包中,方法是链式的。我没有使用过角度,但你能跳到那个位置 url 对象:window.location = this.url; @iceman 如果我理解你的话,是的。为了更清楚,我编辑了问题 查看我编辑的答案以了解如何处理响应 @John's answer using html5 download 可能是您唯一的解决方案。请注意,Safari、IE、Safari-ios、Opera-mini 和一些此类浏览器不支持此特定规范。 【参考方案1】:

真正的交易

你能做的最好的就是分割你的端点。

    一个用于表单和方便在不刷新的情况下出现错误。 然后,成功后,重定向到您的其他端点,该端点仅下载文件。

如果文件在磁盘上并且不是自动生成的并且需要经过身份验证才能下载,您可以将文件隐藏在普通端点后面,进行检查,然后使用 X-Accel-Redirect 标头返回文件nginxX-Sendfile 使用 apache。

破解

免责声明:这更像是一种技巧,而不是最佳解决方案。正如@Iceman 所述,Safari、IE、Safari-iOS、Opera-mini 和一些此类浏览器不支持此特定规范。

在您的服务器端端点中,如果文件可用且没有错误,您可以将标头设置为文件的内容类型(如'application/pdf'),以便自动开始下载。

如果有错误,不要设置header,返回错误的json,通过javascript通知用户。

由于我们不知道背后是什么,这里有一个 python (Django) 示例:

response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename=your_filename.pdf'
response.write(repport.printReport(participantId))
return response

您可以在ajax成功回调中处理响应:

$.ajax(
    url: 'endpoint.php',
    success: function(data) 
        var blob = new Blob([data]);
        var link = document.createElement('a');
        link.href = window.URL.createObjectURL(blob);
        link.download = "filename.pdf";
        link.click();
    
);

您也可以试试这个answer 中提到的jQuery fileDownload 插件。

【讨论】:

这是一个 ajax 请求,下载将开始但异步且对最终用户不可用。 @EmileBergeron 您能否在帖子中提及浏览器支持限制警告,以及您正在使用 html5 下载规范的一点见解 @Iceman 是的,我确实意识到这与其说是一个明确的解决方案,不如说是一个 hack。 @EmileBergeron 只是认为它会在可能的情况下保存请求,并在其他情况下回退并工作,但会产生额外请求的成本。但是,是的,你是对的。保持原样,因为它违反了 OP 的要求 @EmileBergeron 谢谢,我相信这就是我想要的。太糟糕了,它只是一个“黑客”。

以上是关于在 Javascript 中,如何在窗口位置重定向 Ajax 响应的主要内容,如果未能解决你的问题,请参考以下文章

允许获取 chrome 浏览器通知后如何刷新或重定向用户?

Javascript/jquery:如何检测在其他窗口或应用链接中加载的页面?

在 Bootstrap 中,如何使用模态重定向到一个部分(而不重定向到打开模态的位置)

如何在黄瓜中跟踪来自javascript的重定向?

iframe/Popup 重定向开启器窗口

如何在 Javascript 重定向中保留 URL 参数?