Google 驱动器 API 出现奇怪的 CORS 问题
Strange CORS issue with Google Drive API
Google 驱动器 API, files.update:
https://developers.google.com/drive/api/v3/reference/files/update
这个 API 给出了 CORS 错误,奇怪的是在我正在创建的同一个驱动器应用程序中,在同一个域上(我正在直接在线测试它):
- files.create API 运行正常
- files.update API 给我 CORS 错误(浏览器的预检请求找不到允许来源 header 作为响应)
developers.google.com 上的文档没有提到 CORS 问题,一个 API 可以而另一个不能的问题可能是什么?
创建和更新的 2 个函数在这里,但不应该是代码问题,因为 CORS 是关于脚本的起源,而函数在同一页上:
// Create new file in Gdrive
// See: https://developers.google.com/drive/api/v3/reference/files/create
// See: https://tanaikech.github.io/2018/08/13/upload-files-to-google-drive-using-javascript
async function gdrive_create_file(Folder_Id,File_Name,Binobj){
var Metadata = {
"name": File_Name, // Filename at Google Drive
"mimeType": "text/plain", // mimeType at Google Drive
"parents": [Folder_Id], // Folder ID at Google Drive
};
// Here gapi is used for retrieving the access token.
var Access_Token = gapi.auth.getToken().access_token;
var Form = new FormData();
Form.append("metadata", new Blob([JSON.stringify(Metadata)], {type: 'application/json'}));
Form.append("file", Binobj);
// Make request to Gdrive
var [Lock,Unlock] = new_lock();
var File_Id = null;
var Xhr = new XMLHttpRequest();
// Gdrive to return id as indicated in 'fields=id'
Xhr.open(
"post",
"https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id"
);
Xhr.setRequestHeader("Authorization", "Bearer "+Access_Token);
Xhr.responseType = "json";
Xhr.onload = ()=>{
log("[Dad's TE] Gdrive file id:",Xhr.response.id); // Retrieve uploaded file ID.
File_Id = Xhr.response.id;
if (File_Id==null)
alert("Failed to create file in Gdrive!");
Unlock();
};
Xhr.send(Form);
// Wait to get resulting file id
await Lock;
return File_Id;
}
// Update a file in Gdrive
log("DEBUG HERE: 0");
async function gdrive_update_file(File_Id,File_Name,Binobj){
var Metadata = {
"name": File_Name, // Filename at Google Drive
"mimeType": "text/plain" // mimeType at Google Drive
};
// Here gapi is used for retrieving the access token.
var Access_Token = gapi.auth.getToken().access_token;
var Form = new FormData();
Form.append("metadata", new Blob([JSON.stringify(Metadata)], {type: 'application/json'}));
Form.append("file", Binobj);
// Make request to Gdrive
var [Lock,Unlock] = new_lock();
var Xhr = new XMLHttpRequest();
// Gdrive to return id as indicated in 'fields=id'
Xhr.open(
"patch",
`https://www.googleapis.com/upload/drive/v3/files/${File_Id}?uploadType=multipart&fields=id`
);
Xhr.setRequestHeader("Authorization", "Bearer "+Access_Token);
Xhr.responseType = "json";
Xhr.onload = ()=>{
log("[Dad's TE] Gdrive file id:",Xhr.response.id); // Retrieve uploaded file ID.
File_Id = Xhr.response.id;
if (File_Id==null)
alert("Failed to update file in Gdrive!");
Unlock();
};
alert("DEV ERROR: See CORS error in console log!");
Xhr.send(Form);
// Wait to get resulting file id
await Lock;
return File_Id;
}
new_lock
函数:
function new_lock(){
var Unlock,Lock = new Promise((Res,Rej)=>{ Unlock=Res; });
return [Lock,Unlock];
}
在你的脚本中,修改如下?在我的环境中,当我测试你的脚本时,我确认了同样的错误。在这种情况下,当"patch"
修改为"PATCH"
时,错误被移除。
修改后的脚本:
发件人:
Xhr.open(
"patch",
`https://www.googleapis.com/upload/drive/v3/files/${File_Id}?uploadType=multipart&fields=id`
);
收件人:
Xhr.open(
"PATCH",
`https://www.googleapis.com/upload/drive/v3/files/${File_Id}?uploadType=multipart&fields=id`
);
或
Xhr.open(
"PATCH",
"https://www.googleapis.com/upload/drive/v3/files/" + File_Id + "?uploadType=multipart&fields=id"
);
- 另外,请删除
alert("DEV ERROR: See CORS error in console log!");
。使用时,始终显示。请注意这一点。
- 当
console.log(Xhr.response);
被放入Xhr.onload = ()=>{,,,}
时,可以看到API的响应。
注:
在我用"PATCH"
更新文件后,当我用"patch"
测试脚本时,没有发生错误。但是,当使用 "patch"
的脚本更新新文件时,再次出现此类错误。那么在这种情况下,使用 "PATCH"
而不是 "patch"
怎么样?
作为简单的测试脚本,下面的脚本怎么样?
function gdrive_update_file(File_Id,File_Name,Binobj){
var Metadata = { "name": File_Name, "mimeType": "text/plain" };
var Access_Token = gapi.auth.getToken().access_token;
var Form = new FormData();
Form.append("metadata", new Blob([JSON.stringify(Metadata)], { type: 'application/json' }));
Form.append("file", Binobj);
var Xhr = new XMLHttpRequest();
Xhr.open(
"PATCH",
"https://www.googleapis.com/upload/drive/v3/files/" + File_Id + "?uploadType=multipart&fields=id"
);
Xhr.setRequestHeader("Authorization", "Bearer " + Access_Token);
Xhr.responseType = "json";
Xhr.onload = () => {
console.log(Xhr.response);
};
Xhr.send(Form);
}
参考文献:
Google 驱动器 API, files.update:
https://developers.google.com/drive/api/v3/reference/files/update
这个 API 给出了 CORS 错误,奇怪的是在我正在创建的同一个驱动器应用程序中,在同一个域上(我正在直接在线测试它):
- files.create API 运行正常
- files.update API 给我 CORS 错误(浏览器的预检请求找不到允许来源 header 作为响应)
developers.google.com 上的文档没有提到 CORS 问题,一个 API 可以而另一个不能的问题可能是什么?
创建和更新的 2 个函数在这里,但不应该是代码问题,因为 CORS 是关于脚本的起源,而函数在同一页上:
// Create new file in Gdrive
// See: https://developers.google.com/drive/api/v3/reference/files/create
// See: https://tanaikech.github.io/2018/08/13/upload-files-to-google-drive-using-javascript
async function gdrive_create_file(Folder_Id,File_Name,Binobj){
var Metadata = {
"name": File_Name, // Filename at Google Drive
"mimeType": "text/plain", // mimeType at Google Drive
"parents": [Folder_Id], // Folder ID at Google Drive
};
// Here gapi is used for retrieving the access token.
var Access_Token = gapi.auth.getToken().access_token;
var Form = new FormData();
Form.append("metadata", new Blob([JSON.stringify(Metadata)], {type: 'application/json'}));
Form.append("file", Binobj);
// Make request to Gdrive
var [Lock,Unlock] = new_lock();
var File_Id = null;
var Xhr = new XMLHttpRequest();
// Gdrive to return id as indicated in 'fields=id'
Xhr.open(
"post",
"https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id"
);
Xhr.setRequestHeader("Authorization", "Bearer "+Access_Token);
Xhr.responseType = "json";
Xhr.onload = ()=>{
log("[Dad's TE] Gdrive file id:",Xhr.response.id); // Retrieve uploaded file ID.
File_Id = Xhr.response.id;
if (File_Id==null)
alert("Failed to create file in Gdrive!");
Unlock();
};
Xhr.send(Form);
// Wait to get resulting file id
await Lock;
return File_Id;
}
// Update a file in Gdrive
log("DEBUG HERE: 0");
async function gdrive_update_file(File_Id,File_Name,Binobj){
var Metadata = {
"name": File_Name, // Filename at Google Drive
"mimeType": "text/plain" // mimeType at Google Drive
};
// Here gapi is used for retrieving the access token.
var Access_Token = gapi.auth.getToken().access_token;
var Form = new FormData();
Form.append("metadata", new Blob([JSON.stringify(Metadata)], {type: 'application/json'}));
Form.append("file", Binobj);
// Make request to Gdrive
var [Lock,Unlock] = new_lock();
var Xhr = new XMLHttpRequest();
// Gdrive to return id as indicated in 'fields=id'
Xhr.open(
"patch",
`https://www.googleapis.com/upload/drive/v3/files/${File_Id}?uploadType=multipart&fields=id`
);
Xhr.setRequestHeader("Authorization", "Bearer "+Access_Token);
Xhr.responseType = "json";
Xhr.onload = ()=>{
log("[Dad's TE] Gdrive file id:",Xhr.response.id); // Retrieve uploaded file ID.
File_Id = Xhr.response.id;
if (File_Id==null)
alert("Failed to update file in Gdrive!");
Unlock();
};
alert("DEV ERROR: See CORS error in console log!");
Xhr.send(Form);
// Wait to get resulting file id
await Lock;
return File_Id;
}
new_lock
函数:
function new_lock(){
var Unlock,Lock = new Promise((Res,Rej)=>{ Unlock=Res; });
return [Lock,Unlock];
}
在你的脚本中,修改如下?在我的环境中,当我测试你的脚本时,我确认了同样的错误。在这种情况下,当"patch"
修改为"PATCH"
时,错误被移除。
修改后的脚本:
发件人:
Xhr.open(
"patch",
`https://www.googleapis.com/upload/drive/v3/files/${File_Id}?uploadType=multipart&fields=id`
);
收件人:
Xhr.open(
"PATCH",
`https://www.googleapis.com/upload/drive/v3/files/${File_Id}?uploadType=multipart&fields=id`
);
或
Xhr.open(
"PATCH",
"https://www.googleapis.com/upload/drive/v3/files/" + File_Id + "?uploadType=multipart&fields=id"
);
- 另外,请删除
alert("DEV ERROR: See CORS error in console log!");
。使用时,始终显示。请注意这一点。 - 当
console.log(Xhr.response);
被放入Xhr.onload = ()=>{,,,}
时,可以看到API的响应。
注:
在我用
"PATCH"
更新文件后,当我用"patch"
测试脚本时,没有发生错误。但是,当使用"patch"
的脚本更新新文件时,再次出现此类错误。那么在这种情况下,使用"PATCH"
而不是"patch"
怎么样?作为简单的测试脚本,下面的脚本怎么样?
function gdrive_update_file(File_Id,File_Name,Binobj){ var Metadata = { "name": File_Name, "mimeType": "text/plain" }; var Access_Token = gapi.auth.getToken().access_token; var Form = new FormData(); Form.append("metadata", new Blob([JSON.stringify(Metadata)], { type: 'application/json' })); Form.append("file", Binobj); var Xhr = new XMLHttpRequest(); Xhr.open( "PATCH", "https://www.googleapis.com/upload/drive/v3/files/" + File_Id + "?uploadType=multipart&fields=id" ); Xhr.setRequestHeader("Authorization", "Bearer " + Access_Token); Xhr.responseType = "json"; Xhr.onload = () => { console.log(Xhr.response); }; Xhr.send(Form); }