将数据发布到 JsonP

发布于 2024-08-29 15:36:17 字数 115 浏览 2 评论 0 原文

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

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

解决此问题的选项有哪些?

Is it possible to post data to JsonP? Or does all data have to be passed in the querystring as a GET request?

I have alot of data that I need to send to the service, cross domain, and it is too large to send via the querystring

What are the options for getting around this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

相对绾红妆 2024-09-05 15:36:17

由于 同源策略。 JSON-P 之所以有效,是因为您可以将

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

编辑:有一些有趣的技巧,如果您愿意付出大量努力插入隐藏的

It is not possible to do an asynchronous POST to a service on another domain, due to the (quite sensible) limitation of the same origin policy. JSON-P only works because you're allowed to insert <script> tags into the DOM, and they can point anywhere.

You can, of course, make a page on another domain the action of a regular form POST.

Edit: There are some interesting hacks out there if you're willing to go to a lot of effort inserting hidden <iframe>s and mucking about with their properties.

何其悲哀 2024-09-05 15:36:17

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

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

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

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

If you need to send a lot of data cross-domain. I usually create a service that you can call in two steps:

  1. First the client do a FORM submit (post allowed cross domain). The service stores the input in the session on the server (using the GUID as key). (the client creates a GUID and send's it as a part of the input)

  2. Then the client do a normal script-inject (JSONP) as a parameter you use the same GUID as you used in the FORM post. The service processes the input from the session and returns the data in the normal JSONP-fashion. After this the session is destroyed.

This of course relies on that you write the server-backend.

紫竹語嫣☆ 2024-09-05 15:36:17

我知道这是严重的死灵术,但我想我应该使用 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;
}

I know this is serious necromancy, but I thought I'd post my implementation of JSONP POST using jQuery, which I'm successfully using for my JS widget (this is used for customer registration and login):

Basically, I'm using an IFrame approach, as suggested in the accepted answer. What I'm doing differently is after sending the request, I'm watchin, if the form can be reached in the iframe, using a timer. When the form cannot be reached, it means the request has returned. Then, I'm using a normal JSONP request to query for the status of the operation.

I hope that someone finds it useful. Tested in >=IE8, Chrome, FireFox and 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;
}
呆头 2024-09-05 15:36:17

一般来说,JSONP 是通过向调用文档添加

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

Well generally JSONP is implemented by adding a <script> tag to the calling document, such that the URL of the JSONP service is the "src". The browser fetches script source with an HTTP GET transaction.

Now, if your JSONP service is in the same domain as your calling page, then you could probably cobble something together with a simple $.ajax() call. If it's not in the same domain, then I'm not sure how it'd be possible.

做个少女永远怀春 2024-09-05 15:36:17

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

You could use a CORS Proxy using this project. It would direct all traffic to an endpoint on your domain and relay that information to an external domain. Since the browser is registering all requests to be on the same domain we are able to post JSON.
NOTE: This also works with SSL certificates held on the server.

神经暖 2024-09-05 15:36:17

有一个(黑客)解决方案我已经做过很多次了,你将能够使用 JsonP 发布。
(您将能够发布表单,大于 2000 个字符,超过您可以通过 GET 使用的字符)

客户端应用程序 Javascript

$.ajax({
  type: "POST", // you request will be a post request
  data: postData, // javascript object with all my params
  url: COMAPIURL, // my backoffice comunication api url
  dataType: "jsonp", // datatype can be json or jsonp
  success: function(result){
    console.dir(result);
  }
});

JAVA:

response.addHeader( "Access-Control-Allow-Origin", "*" ); // open your api to any client 
response.addHeader( "Access-Control-Allow-Methods", "POST" ); // a allow post
response.addHeader( "Access-Control-Max-Age", "1000" ); // time from request to response before timeout

PHP:

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Max-Age: 1000');

像这样,您正在向任何发布请求开放服务器,您应该通过提供身份或其他内容来重新保护它。

使用此方法,您还可以将请求类型从 jsonp 更改为 json,两者都可以,只需设置正确的响应内容类型

jsonp

response.setContentType( "text/javascript; charset=utf-8" );

json

response.setContentType( "application/json; charset=utf-8" );

请注意,您的服务器将不再尊重SOP(同源政策),但谁在乎呢?

There's a (hack) solution I've did it many times, you'll be able to Post with JsonP.
(You'll be able to Post Form, bigger than 2000 char than you can use by GET)

Client application Javascript

$.ajax({
  type: "POST", // you request will be a post request
  data: postData, // javascript object with all my params
  url: COMAPIURL, // my backoffice comunication api url
  dataType: "jsonp", // datatype can be json or jsonp
  success: function(result){
    console.dir(result);
  }
});

JAVA:

response.addHeader( "Access-Control-Allow-Origin", "*" ); // open your api to any client 
response.addHeader( "Access-Control-Allow-Methods", "POST" ); // a allow post
response.addHeader( "Access-Control-Max-Age", "1000" ); // time from request to response before timeout

PHP:

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Max-Age: 1000');

Doing like this, you are opening your server to any post request, you should re-secure this by providing ident or something else.

With this method, you could also change the request type from jsonp to json, both work, just set the right response content type

jsonp

response.setContentType( "text/javascript; charset=utf-8" );

json

response.setContentType( "application/json; charset=utf-8" );

Please not that you're server will no more respect the SOP (same origin policy), but who cares ?

玩物 2024-09-05 15:36:17

有可能,这是我的解决方案:

在您的 javascript 中:

jQuery.post("url.php",data).complete(function(data) {
    eval(data.responseText.trim()); 
});
function handleRequest(data){
    ....
}

在您的 url.php 中:

echo "handleRequest(".$responseData.")";

It is possible, here is my solution:

In your javascript:

jQuery.post("url.php",data).complete(function(data) {
    eval(data.responseText.trim()); 
});
function handleRequest(data){
    ....
}

In your url.php:

echo "handleRequest(".$responseData.")";
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文