5

我正在使用 Google JavaScript API 在 web 应用程序中获取 google 联系人,并且我想检索他们的图片。

我正在做这样的事情(高度简化):

var token; // let's admit this is available already

function getPhotoUrl(entry, cb) {
  var link = entry.link.filter(function(link) {
    return link.type.indexOf("image") === 0;
  }).shift();
  if (!link)
    return cb(null);
  var request = new XMLHttpRequest();
  request.open("GET", link.href + "?v=3.0&access_token=" + token, true);
  request.responseType = "blob";
  request.onload = cb;
  request.send();
}

function onContactsLoad(responseText) {
  var data = JSON.parse(responseText);
  (data.feed.entry || []).forEach(function(entry) {
    getPhotoUrl(e, function(a, b, c) {
      console.log("pic", a, b, c);
    });
  });
}

但是我在 Chrome 和 Firefox 中都遇到了这个错误:

跨域请求被阻止:同源策略不允许在https://www.google.com/m8/feeds/photos/media/<user_email >/<some_contact_id>?v=3.0&access_token=<obfuscated>读取远程资源. 这可以通过将资源移动到同一域或启用 CORS 来解决。

当查看来自 feeds/photos 端点的响应标头时,我可以看到它Access-Control-Allow-Origin: *没有发送,因此我得到了 CORS 错误。

请注意,Access-Control-Allow-Origin: *在到达feeds/contacts端点时发送,因此允许跨域请求。

这是一个错误,还是我错过了他们文档中的某些内容?

4

2 回答 2

2

假设您只需要“个人资料图片”,请尝试通过将完整 URL 设置为标记src元素(末尾带有 a),将对该图像的请求直接移动到 HTML 中。<img>?access_token=<youknowit>

例如使用 Angular.js

<img ng-src="{{contact.link[1].href + tokenForImages}}" alt="photo" />

一般来说,对于 CORS,似乎有很多地方从 JS 访问 API 没有按预期工作。

希望这可以帮助。

于 2014-06-01T12:21:34.183 回答
2

还不能发表评论,因此这个答案......</p>

显然,您已经在Google 开发人员控制台中设置了正确的客户端 ID 和 JavaScript 来源。

似乎域共享联系人 API不像宣传的那样工作,并且仅在您请求JSONP数据时遵守其 CORS 承诺(您的代码表明您使用 JSON 获取条目数据)。对于 JSON 格式,API 将 设置access-control-allow-origin为 * 而不是您为项目列出的 JavaScript 来源。

但是从今天(2015-06-16)开始,如果您尝试使用不同的数据类型(例如/ )发出GET, POST... ,Google API 根本不会设置 access-control-allow-origin ,因此您的浏览器将拒绝您访问数据的请求(错误 405)。atomxml

这显然是一个错误,它阻止了对共享联系人 API 的任何编程使用,但对于条目的简单列表:不能再创建、更新、删除条目或访问照片。

如果我错了,请纠正我(我希望我是);如果您知道向 Google 提交此错误的最佳方式,请发表评论或编辑。

注意,为了完整起见,这里是我用来访问联系人的代码框架(需要 jQuery)。

    <button id="authorize-button" style="visibility: hidden">Authorize</button>
    <script type="text/javascript">
        var clientId = 'TAKE-THIS-FROM-CONSOLE.apps.googleusercontent.com',
            apiKey = 'TAKE-THAT-FROM-GOOGLE-DEVELOPPERS-CONSOLE',
            scopes = 'https://www.google.com/m8/feeds';
        // Use a button to handle authentication the first time.
        function handleClientLoad () {
            gapi.client.setApiKey ( apiKey );
            window.setTimeout ( checkAuth, 1 );
        }
        function checkAuth() {
            gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult);
        }
        function handleAuthResult ( authResult ) {
            var authorizeButton = document.getElementById ( 'authorize-button' );
            if ( authResult && !authResult.error ) {
                authorizeButton.style.visibility = 'hidden';
                var cif = {
                    method: 'GET',
                    url:  'https://www.google.com/m8/feeds/contacts/mydomain.com/full/',
                    data: {
                        "access_token": authResult.access_token,
                        "alt":          "json",
                        "max-results":  "10"
                    },
                    headers: { 
                        "Gdata-Version":    "3.0"    
                    },
                    xhrFields: {
                        withCredentials: true
                    },
                    dataType: "jsonp"
                };
                $.ajax ( cif ).done ( function ( result ) {
                        $ ( '#gcontacts' ).html ( JSON.stringify ( result, null, 3 ) );
                } );
            } else {
                authorizeButton.style.visibility = '';
                authorizeButton.onclick = handleAuthClick;
            }
        }
        function handleAuthClick ( event ) {
            gapi.auth.authorize ( { client_id: clientId, scope: scopes, immediate: false }, handleAuthResult );
            return false;
        }
    </script>
    <script src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>
    <pre id="gcontacts"></pre>

如果你替换cif.data.altbyatom和/或cif.dataTypeby xml,你会得到臭名昭著的错误 405。

ps:cif当然和ajax有关;-)

于 2015-06-16T07:17:54.950 回答