问题描述
更新:这是GoogleDrive中的错误,CORS未启用上传URI。 @ Nivco指示我使用Google的客户端库使用iframe和代理(不是CORS)。我把(测试过的)工作代码放在底部,以及详细的解释。请参阅下面的示例答案。
Update: This is a bug in GoogleDrive, CORS is not enabled for upload URIs. @Nivco pointed me to a work around with Google's client library which uses an iframe and a proxy (not CORS). I'm putting the (tested) working code at the bottom, along with a detailed explanation. Please see the answer, below for the example.
和表示上传端点支持CORS,但我无法使用它们。我可以使用获取授权并插入一个空文件,但我无法上传内容 - 当我使用,当我使用示例中提供的两种技术插入文件堆栈溢出后。
Inserting File to Google Drive through API and Authorization of Google Drive using JavaScript say that the upload endpoints support CORS, but I haven't been able to use them. I can get authorization and insert an empty file, using Files: insert, but I can't upload content to it -- I get a 405 (Method not allowed) error when I use https://www.googleapis.com/upload/drive/v2/files when I use either of the two techniques given in the example in the inserting file stack overflow post.
CORS是否可以工作在v1版本,并且尚未启用v2?
Is it possible that CORS worked for v1 and hasn't been enabled for v2?
编辑:顺便说一下,405错误
By the way, the 405 error is on the OPTIONS request that chrome is making.
编辑:这是我的一个尝试的代码:
Here's the code from one of my attempts:
在我介绍代码之前,我想强调,我能够验证和列出文件。我只是无法将数据上传到文件。
Before I present the code I want to highlight that I am able to authenticate and list files. I just can't upload data to a file.
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart');
xhr.setRequestHeader('Authorization', 'Bearer ' + params.access_token);
xhr.setRequestHeader("Content-Type", 'multipart/related; boundary="END_OF_PART"');
xhr.onreadystatechange = function(data) {
if (xhr.readyState == DONE) {
document.getElementById("files").innerHTML = "Uploaded file: " + xhr.responseText;
};
}
xhr.send([
mimePart("END_OF_PART", "application/json", json),
mimePart("END_OF_PART", "text/plain", "a\nb\n"),
"\r\n--END_OF_PART--\r\n",
].join(''));
function mimePart(boundary, mimeType, content) {
return [
"\r\n--", boundary, "\r\n",
"Content-Type: ", mimeType, "\r\n",
"Content-Length: ", content.length, "\r\n",
"\r\n",
content,
].join('');
}
以下是请求:
Request URL:https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart
Request Method:OPTIONS
这是响应:
Status Code:405 Method Not Allowed
cache-control:no-cache, no-store, must-revalidate
content-length:0
content-type:text/html; charset=UTF-8
date:Mon, 23 Jul 2012 22:41:29 GMT
expires:Fri, 01 Jan 1990 00:00:00 GMT
pragma:no-cache
server:HTTP Upload Server Built on Jul 17 2012 16:15:04 (1342566904)
status:405 Method Not Allowed
version:HTTP/1.1
没有响应,因为Chrome为该OPTIONS请求提供405错误。没有POST,因为Chrome无法继续,因为它的OPTIONS请求失败,405,因此它在控制台中输出此错误:
There is no response, because Chrome gets a 405 error for that OPTIONS request. There is no POST, because Chrome can't proceed, since its OPTIONS request failed with a 405, and so it prints this error in the console:
XMLHttpRequest cannot load https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart. Origin https://leisurestorage.appspot.com is not allowed by Access-Control-Allow-Origin.
推荐答案
通过使用@ Nivco的帮助以及详细说明,工作代码,
This answer (and in fact the question itself) is now redundant given full CORS support as confirmed by Steve Bazyl
工作代码,
这是一个完整测试这个技术的工作代码。要使用这个,你需要做两个页面。第一页验证并启动第二页,这是您的实际应用程序。为了能够访问Google云端硬盘API以上传文件,您需要注册一个应用程序,其描述为。
Here is the working code for a full test of this technique. To use this, you need to make two pages. The first page authenticates and launches the second page, which is your actual app. In order to be able to access the Google Drive API to upload a file, you need to register an app, which is described here.
您的第一页将使用OAuth,在。它使用以下片段调用您的应用:
Your first page will use OAuth, which is described in this Stackoverflow answer. It calls your app with a fragment that looks like this:
#access_token=ya29.AHES6ZSb4M4ju8U_X_zgFrz_MD2RsjrQu5V05HjsBtrCl0nh2SrnaA&token_type=Bearer&expires_in=3600
在JavaScript中,您可以使用 location.hash
。保存值后,最好立即将 location.hash
设置为空字符串,以便它不会显示在浏览器的位置栏中。您的应用程式需要使用CORS要求中的片段中的access_token值,以及上传API的Proxy(非CORS)要求中的值。这里是一个示例启动页面,它只是一个来自OAuth示例的代码版本:
In JavaScript, you can access that fragment with location.hash
. After you save the value, it's a good idea to set location.hash
to the empty string right away, so that it doesn't show up in the browser's location bar. Your app needs to use the value of access_token from the fragment in its CORS requests and also in the proxied (non-CORS) request to the upload API. Here is an example launch page, which is really just a version of the code from OAuth example:
<html>
<body>
<a href="javascript:poptastic('https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file&client_id=270759921607.apps.googleusercontent.com&redirect_uri=https://leisurestorage.appspot.com&response_type=token');">Authorize Leisure Storage</a><br>
<script>
function poptastic(url) {
var newWindow = window.open(url, 'name', 'height=600,width=450');
if (window.focus) {
newWindow.focus();
}
}
</script>
</body>
</html>
这里是一个示例应用程序,上传 a\\\
到您的GoogleDrive中的
a\b\\ \\ n leisureUpload
文件,使用Google的JavaScript客户端库。没有必要使用任何gapi.auth方法,因为它使用一个原始的gapi.client.request()调用与直接在调用的Authorization头,就像使用CORS的xmlHttpRequest():
Here is an example app that uploads a\na\b\n
to a file called leisureUpload
in your GoogleDrive, using Google's Client Library for JavaScript. There is no need to use any of the gapi.auth methods, because it uses a raw gapi.client.request() call with the Authorization header directly in the call, just like it would with xmlHttpRequest() using CORS:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Leisure</title>
<script type="text/javascript">
var hash = location.hash.substring(1).split('&');
location.hash = '';
var params = {};
for (var i = 0; i < hash.length; i++) {
var p = hash[i].split('=');
params[p[0]] = p[1];
}
function gapiClientLoaded() {/* do nothing */}
function uploadTestFile() {
var json = JSON.stringify({
mimeType: 'text/plain',
title: 'leisureUpload',
});
var xhr = new XMLHttpRequest();
gapi.client.request({
'path': '/upload/drive/v1/files',
'method': 'POST',
'params': {'uploadType': 'multipart'},
'headers': {
'Content-Type': 'multipart/mixed; boundary="END_OF_PART"',
'Authorization': 'Bearer ' + params.access_token,
},
'body': [
mimePart("END_OF_PART", "application/json", json),
mimePart("END_OF_PART", "text/plain", "a\nb\n"),
"\r\n--END_OF_PART--\r\n",
].join('')
}).execute(function(file) {
document.getElementById("result").innerHTML = "Uploaded file: " + file;
});
}
function mimePart(boundary, mimeType, content) {
return [
"\r\n--", boundary, "\r\n",
"Content-Type: ", mimeType, "\r\n",
"Content-Length: ", content.length, "\r\n",
"\r\n",
content,
].join('');
}
</script>
<script src="https://apis.google.com/js/client.js?onload=gapiClientLoaded"></script>
</head>
<body>
<h1>Welcome to Leisure!</h1>
<button onclick="uploadTestFile()">Upload Test File</button><br>
<pre id="result"></pre>
</body>
</html>
这篇关于https://www.googleapis.com/upload/drive/v2/files是否真的支持CORS?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!