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

In Javascript how can I redirect an Ajax response in window location

本文关键字:位置 重定向 Ajax 响应 窗口 Javascript      更新时间:2023-09-26

我目前有以下工作代码(有角度,但适用于任何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) = Action{implicit request =>
   myForm.bindFromRequest.fold(
     e => BadRequest(myErrors),
     v => if(onlyDoCheck) Ok(simpleOkResponse) else  Ok(doComputationgeneratefileandoutputfile)
   )
}

真正的交易

你能做的最好的事情就是拆分你的端点。

  1. 一个是为了形式和在不刷新的情况下出现错误的便利性
  2. 然后,一旦成功,重定向到只下载文件的另一个端点

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

黑客

免责声明:这更像是一个黑客攻击,而不是最佳解决方案。正如@Iceman所提到的,Safari、IE、Safari iOS、Opera mini和一些这样的浏览器不支持这个特定的规范。

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

如果有错误,不要设置头,并返回错误的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();
    }
});

你也可以试试这个答案中提到的jQueryfileDownload插件。