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

在Javascript中,如何在窗口位置重定向Ajax响应,javascript,Javascript,我目前有以下工作代码(但适用于任何JS框架): 以上是在表单完成并且用户单击“提交”后调用的(实际情况比这要复杂一些,但这是相同的想法)。我异步执行表单检查,因此不需要重新加载页面 如果请求成功,则返回一个二进制文件(pdf文件);如果请求不成功,则返回一个错误为JS格式的请求。所以我要做的是,如果成功的话,我重定向到相同的url以获得PDF,否则我会得到JSON错误对象并对其进行处理 如果请求成功,我如何避免提出两个请求 注1:在后端,我只想保留一条路线,它可以完成所有事情,检查并返回PDF

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

以上是在表单完成并且用户单击“提交”后调用的(实际情况比这要复杂一些,但这是相同的想法)。我异步执行表单检查,因此不需要重新加载页面

如果请求成功,则返回一个二进制文件(pdf文件);如果请求不成功,则返回一个错误为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 framework/Scala)

真正的交易 最好是拆分端点

  • 一个是为了便于在不刷新的情况下出现错误
  • 然后,成功后,重定向到仅下载文件的其他端点
  • 如果该文件位于磁盘上,并且不是自动生成的,并且需要经过身份验证才能下载,则可以将该文件隐藏在正常端点后面,进行检查,然后使用nginx的
    X-Accel-Redirect
    头或使用apache的
    X-Sendfile
    返回该文件

    黑客 免责声明:这与其说是最好的解决方案,不如说是一种黑客行为。正如前面提到的,Safari、IE、Safari iOS、Opera mini和一些类似的浏览器不支持此特定规范

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

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

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

    您可以在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();
        }
    });
    

    您也可以尝试本文中提到的插件

    你们看到了吗:url在一个对象闭包中,方法是链式的。我没有使用angular,但是你能用:window.location=this.url跳到那个位置url对象吗@冰人,如果我没听错的话,是的。我对问题进行了编辑,以便更清楚地了解如何处理问题。请参阅我编辑的答案response@John使用HTML5
    download
    的答案可能是您唯一的解决方案。请注意,Safari、IE、Safari iOS、Opera mini等浏览器不支持此特定规范。这是一个ajax请求,下载将开始,但异步且最终用户不可用。@EmileBergeron您能否在帖子中提及浏览器支持限制警告,以及您正在使用html5下载的一些细节spec@Iceman对我确实意识到这与其说是一个清晰的解决方案,不如说是一个黑客手段。@Emilebergron只是认为它可以在可能的情况下保存一个请求,在其他情况下,它可以回退并工作,但需要额外请求的成本。但是,是的,你是对的。让它保持原样,因为它与OP的相反requirements@EmileBergeron谢谢,我相信这就是我想要的。可惜这只是一个“黑客”。
    def myendpoint(onlyDoCheck: Boolean = false) = Action{implicit request =>
       myForm.bindFromRequest.fold(
         e => BadRequest(myErrors),
         v => if(onlyDoCheck) Ok(simpleOkResponse) else  Ok(doComputationgeneratefileandoutputfile)
       )
    }
    
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=your_filename.pdf'
    response.write(repport.printReport(participantId))
    return response
    
    $.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();
        }
    });