在通过常规表单提交或Ajax请求访问时使浏览器重定向的表单 - 这可能吗?

时间:2009-09-22 22:15:01

标签: php javascript jquery html ajax

我有一个带有表单的网页。当用户提交表单时,我希望服务器使浏览器重定向到表单操作的不同页面。现在,我通过使用PHP的header函数来发送302状态代码。它工作正常。

我试图让服务器上的页面以相同的方式重定向浏览器,无论它是否正常提交(没有Javascript)或通过Ajax。我尝试通过将窗口位置设置为Location头中的任何URL来实现此目的。我正在使用jQuery,并进行如下调用:

$.ajax({
    url: this.action,
    type: "POST",
    data: getFormData(this),
    complete: function(request) {
        window.location.assign(request.getResponseHeader("Location"));
    }
});

然而,这不起作用。在考虑之后,我意识到这并不是很令人惊讶。在Ajax请求中,浏览器应该在更改readyState之前透明地处理重定向响应,例如302代码。当完整的函数运行时,它正在查找最终目标中的Location标头而没有找到它。

作为实验,我尝试使用Location标头发送200状态代码。我尝试了Ajax请求,它工作正常。但是,当我执行非Ajax提交时,它不起作用。浏览器转到表单操作页面并停留在那里,就像它忽略了Location标题一样。

在两种情况下是否有任何方法可以使同一页面重定向,而服务器不必知道或关心请求是否是Ajax请求?

如果这很重要,我在各种浏览器(IE8,IE7,IE6,Firefox 3.5,Chrome)中尝试了表格,每次都有类似的结果。此外,我正在做一个帖子请求,以避免碰到IE的2083字符URL长度限制。

8 个答案:

答案 0 :(得分:5)

HTTP 302 response are consumed silently by XmlHttpRequest implementations(例如jQuery的ajax函数)。这是一个特色。

我过去解决这个问题的方法是检测XmlHttpRequests并发出"Content-Location" header(而不是"Location"标头)。最常用的跨库方法是检查服务器端代码中的"X-Requested-With" http标头(jQuery,Prototype,Mootools等设置此代码):

if (@$_SERVER['HTTP_X_REQUESTED_WITH']  == 'XMLHttpRequest') {
    header('Content-Location: ' . $redirect_url);
} else {
    header('Location: ' . $redirect_url);
}

您仍然需要特殊情况下的客户端代码:

$.ajax({
    // ...
    complete: function(xhr) {
        var redirect_url = xhr.getResponseHeader("Content-Location");
        if (redirect_url) {
            window.location = redirect_url;
        }
    }
})

答案 1 :(得分:0)

如果用户被重定向,为什么选择Ajax?像这样的Ajax的重点是在没有页面刷新的情况下对页面进行更改,因此您使用的技术看起来有点像构建输出到碎纸机漏斗的打印机。

答案 2 :(得分:0)

我想更多地了解您的用例。从我的理解你试图让你的应用程序加载基于Ajax调用的'Location'标题的页面?我问为什么?

HTTP标头似乎是从中获取该信息的正确位置。您的应用程序本质上不是在进行“我应该在何处重定向到?”的查询。没有理由Ajax响应实际上必须使用302和“Location”标头进行响应。为什么不让它使用包含新URL的JSON或XML进行响应?

编辑:重新阅读倒数第二段。我不确定有什么好方法可以达到你想要的效果。这个概念听起来很糟糕。 :)

答案 3 :(得分:0)

将附加参数传递给您的ajax请求,以便轻松识别请求类型。当ajax - 不重定向 - 只需发送目标url,然后通过location.href重定向客户端ajax回调

像这样:

$.post('/controller/action', {formdata}, function (redirect_to) {
    location.href = redirect_to;
});

答案 4 :(得分:0)

将“完成”工作:

$.ajax({
    type: frm.attr('method'),
    url: frm.attr('action'),
    data: frm.serialize(),
    complete: complete(xhr, status) {
       window.location.assign(xhr.getResponseHeader("Location"));

    }
});

答案 5 :(得分:0)

您是否尝试使用错误功能而非完整?

$.ajax({
    url: this.action,
    type: "POST",
    data: getFormData(this),
    error: function(request) {
        if(request.status == 302)
            window.location.assign(request.getResponseHeader("Location"));
    }
});

jQuery向错误函数发送任何3xx响应。也许在这个阶段仍然可以使用“位置”标题。

答案 6 :(得分:0)

为什么不让您的“ajax动作”只需填写所需的表单字段并提交表单?通过这种方式,您将获得与手动提交时完全相同的行为。

答案 7 :(得分:0)

这是另一种选择,但您需要进行一些跨浏览器测试:

complete: function(request) {
    if(request.status == 200) {
        var doc = document.open(request.getResponseHeader('Content-Type'));
        doc.write(request.responseText);
        doc.close();
    }
}

主要缺点:地址栏中的URL不会改变;可能会混淆后退按钮/历史记录

虽然我认为@ crescentfresh的想法是要走的路