将数据发布到JsonP

Chr*_*sCa 101 javascript ajax jquery json jsonp

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

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

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

fri*_*edo 82

POST由于相同原始策略的(非常合理的)限制,不可能对另一个域上的服务执行异步操作.JSON-P只能工作,因为你可以<script>在DOM中插入标签,它们可以指向任何地方.

当然,您可以在另一个域上创建常规表单POST的操作.

编辑:有一些有趣的黑客,如果你愿意花费大量的精力插入隐藏的<iframe>s和他们的属性.

  • 这不是真的.只要该域和浏览器都支持`CORS`,您当然可以对其他域执行`POST`请求​​.但是`POST`和`JSONP`完全不兼容. (8认同)
  • @mark"同步POST"表示提交使用<form method ="post"action ="http:// .../...">的表单 (4认同)
  • 通过插入指向另一个域的"<script>"标记来实现JSONP.在浏览器中执行POST请求的唯一方法是通过HTML表单或XMLHttpRequest. (2认同)

小智 20

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

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

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

这当然依赖于您编写服务器后端.


W.B*_*.B. 7

我知道这是严重的死灵法术,但我想我会使用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;
}
Run Code Online (Sandbox Code Playgroud)