将数据发布到 JsonP

IT技术 javascript jquery ajax json jsonp
2021-01-11 05:39:39

是否可以将数据发布到 JsonP?还是所有数据都必须作为 GET 请求在查询字符串中传递?

我有很多数据需要发送到服务,跨域,而且太大而无法通过查询字符串发送

有什么办法可以解决这个问题?

6个回答

POST由于同源策略的(非常明智的)限制,不可能对另一个域上的服务执行异步操作JSON-P 之所以有效,是因为您可以将<script>标签插入到 DOM 中,并且它们可以指向任何地方。

当然,您可以使另一个域上的页面成为常规表单 POST 的操作。

编辑如果您愿意付出大量努力插入隐藏的s 并处理它们的属性,那么有一些有趣的技巧<iframe>

你提到“异步 POST”是不可能的......那么我可以做一个同步 POST 吗?
2021-03-11 05:39:39
(一般来说 - )可以(!)对另一个域上的服务执行异步 POST。限制在于响应。限制也在于 JSONP 请求。
2021-03-15 05:39:39
JSONP 是通过插入<script>指向另一个域的标签来实现的在浏览器中执行 POST 请求的唯一方法是通过 HTML 表单或 XMLHttpRequest。
2021-03-20 05:39:39
@mark "同步 POST" 表示提交一个使用 <form method="post" action="http://.../..."> 的表单
2021-03-27 05:39:39
这并不完全正确。您当然可以POST向其他域发出请求,只要该域和您的浏览器都支持CORS. 但这是完全正确的,POST并且JSONP不兼容。
2021-04-04 05:39:39

如果需要跨域发送大量数据。我通常会创建一个服务,您可以分两步调用该服务:

  1. 首先客户端做一个 FORM 提交(允许跨域发布)。该服务将输入存储在服务器上的会话中(使用 GUID 作为键)。(客户端创建一个 GUID 并将其作为输入的一部分发送)

  2. 然后客户端执行正常的脚本注入 (JSONP) 作为参数,您使用与您在 FORM 帖子中使用的 GUID 相同的 GUID。该服务处理来自会话的输入并以正常的 JSONP 方式返回数据。在此之后,会话被销毁。

这当然取决于您编写服务器后端。

尝试了你的方法。适用于 FF14 和 Chrome20。Opera11 和 IE9 只是没有转帖。(用他们的调试工具检查并在另一端的服务器上监听)可能与 IE 的残疾有关的是这个问题:stackoverflow.com/questions/10395803/... Chrome 在控制台中抱怨,但仍然没有 POST:XMLHttpRequest cannot Access-Control-Allow-Origin 不允许加载localhost:8080/xxx Origin null。
2021-03-25 05:39:39
@OneWorld——你没有按照答案做。XMLHttpRequest根本不应该参与。Per 的回答使用常规表单提交来发出 POST 请求,然后使用脚本元素注入来发出 GET 请求。
2021-03-26 05:39:39

我知道这是严重的死灵法术,但我想我会使用 jQuery 发布我的 JSONP POST 实现,我已成功将其用于我的 JS 小部件(这用于客户注册和登录):

基本上,我使用的是 IFrame 方法,如已接受的答案中所建议。我正在做的不同之处是在发送请求后,我正在观察,如果可以使用计时器在 iframe 中访问表单。当无法访问表单时,表示请求已返回。然后,我使用一个普通的 JSONP 请求来查询操作的状态。

我希望有人觉得它有用。在 >=IE8、Chrome、FireFox 和 Safari 中测试。

function JSONPPostForm(form, postUrl, queryStatusUrl, queryStatusSuccessFunc, queryStatusData)
{
    var tmpDiv = $('<div style="display: none;"></div>');
    form.parent().append(tmpDiv);
    var clonedForm = cloneForm(form);
    var iframe = createIFrameWithContent(tmpDiv, clonedForm);

    if (postUrl)
        clonedForm.attr('action', postUrl);

    var postToken = 'JSONPPOST_' + (new Date).getTime();
    clonedForm.attr('id', postToken);
    clonedForm.append('<input name="JSONPPOSTToken" value="'+postToken+'">');
    clonedForm.attr('id', postToken );
    clonedForm.submit();

    var timerId;
    var watchIFrameRedirectHelper = function()
    {
        if (watchIFrameRedirect(iframe, postToken ))
        {
            clearInterval(timerId);
            tmpDiv.remove();
            $.ajax({
                url:  queryStatusUrl,
                data: queryStatusData,
                dataType: "jsonp",
                type: "GET",
                success: queryStatusSuccessFunc
            });
        }
    }

    if (queryStatusUrl && queryStatusSuccessFunc)
        timerId = setInterval(watchIFrameRedirectHelper, 200);
}

function createIFrameWithContent(parent, content)
{
    var iframe = $('<iframe></iframe>');
    parent.append(iframe);

    if (!iframe.contents().find('body').length)
    {
        //For certain IE versions that do not create document content...
        var doc = iframe.contents().get()[0];
        doc.open();
        doc.close();
    }

    iframe.contents().find('body').append(content);
    return iframe;
}

function watchIFrameRedirect(iframe, formId)
{
    try
    {
        if (iframe.contents().find('form[id="' + formId + '"]').length)
            return false;
        else
            return true;
    }
    catch (err)
    {
        return true;
    }
    return false;
}

//This one clones only form, without other HTML markup
function cloneForm(form)
{
    var clonedForm = $('<form></form>');
    //Copy form attributes
    $.each(form.get()[0].attributes, function(i, attr)
    {
        clonedForm.attr(attr.name, attr.value);
    });
    form.find('input, select, textarea').each(function()
    {
        clonedForm.append($(this).clone());
    });

    return clonedForm;
}

通常JSONP是通过<script>在调用文档中添加标签来实现的,这样JSONP服务的URL就是“src”。浏览器通过 HTTP GET 事务获取脚本源。

现在,如果您的 JSONP 服务与您的调用页面在同一个域中,那么您可能可以通过一个简单的$.ajax()调用拼凑一些东西如果它不在同一个域中,那么我不确定这怎么可能。

如果它不在同一个域中但它支持,CORS那么只要浏览器也支持它就可以了。在这些情况下,您将使用 plainJSON而不是JSONP.
2021-03-21 05:39:39
是的,@hippietrail 2 年有很大的不同 :-) CORS 绝对使它成为可能,但当然它确实需要正确设置数据源。
2021-04-03 05:39:39
在这种情况下,它不在同一个域中。我假设只有 GET 是可能的,但想检查一下,因为我今天才开始阅读 JsonP 并且需要就它是否适合我的需要做出一些决定
2021-04-08 05:39:39

您可以使用项目使用CORS 代理它会将所有流量定向到您域上的端点并将该信息中继到外部域。由于浏览器将所有请求注册到同一个域中,我们可以发布 JSON。 注意:这也适用于服务器上保存的 SSL 证书。