更新:这是GoogleDrive中的错误,未启用CORS上传URI。 @Nivco向我指出了使用iframe和代理(不是CORS)的Google客户端库。我将(经过测试的)工作代码放在底部,并附上详细说明。请参阅下面的答案。
Inserting File to Google Drive through API和Authorization of Google Drive using JavaScript表示上传端点支持CORS,但我无法使用它们。我可以使用Files: insert获取授权并插入一个空文件,但我无法上传内容 - 当我使用https://www.googleapis.com/upload/drive/v2/files时,我得到405(不允许方法)错误在插入文件堆栈溢出帖子中的示例中给出的两种技术。
CORS是否可能适用于v1且尚未启用v2?
编辑:顺便说一句,405错误发生在Chrome正在进行的OPTIONS请求上。
编辑:以下是我尝试过的代码:在我提出代码之前,我想强调一下,我能够对文件进行身份验证和列出。我只是无法将数据上传到文件。
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而失败,因此它会在控制台中输出此错误:
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.
答案 0 :(得分:2)
看起来你是对的,上传API端点似乎不支持CORS请求,而其他端点确实支持它(很抱歉未经过彻底测试)。这是一个错误,我们让工程团队知道这个问题。
与此同时,似乎唯一的解决方法是使用Javascript客户端库并利用它使用的iframe代理,如Authorization of Google Drive using JavaScript
中所述感谢你提出这个问题!
答案 1 :(得分:2)
CORS现已完全启用。有关如何使用vanilla JS进行可恢复上传的示例,请参阅https://github.com/googledrive/cors-upload-sample。
答案 2 :(得分:0)
这个答案(事实上问题本身)现在已经多余,因为Steve Bazyl确认了完整的CORS支持
工作代码,使用@ Nivco的帮助,以及详细说明:
这是完整测试此技术的工作代码。要使用它,您需要制作两页。第一页验证并启动第二页,这是您的实际应用程序。为了能够访问Google云端硬盘API以上传文件,您需要注册一个应用,其描述为here。
您的第一页将使用OAuth,this Stackoverflow answer中对此进行了描述。它会使用如下所示的片段调用您的应用:
#access_token=ya29.AHES6ZSb4M4ju8U_X_zgFrz_MD2RsjrQu5V05HjsBtrCl0nh2SrnaA&token_type=Bearer&expires_in=3600
在JavaScript中,您可以使用location.hash
访问该片段。保存该值后,最好立即将location.hash
设置为空字符串,这样它就不会显示在浏览器的位置栏中。您的应用需要在其CORS请求中使用片段中的access_token值,也需要在上载API的代理(非CORS)请求中使用。这是一个示例启动页面,它实际上只是OAuth示例代码的一个版本:
<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>
以下是使用Google的JavaScript客户端库将a\na\b\n
上传到GoogleDrive中名为leisureUpload
的文件的示例应用。不需要使用任何gapi.auth方法,因为它直接在调用中使用带有Authorization头的原始gapi.client.request()调用,就像使用CORS的xmlHttpRequest()一样:
<!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>