Sample1:授权
概述
主要分为五步:
加载api工具库
登陆
scopes授权
-
加载对应的工具文档
- 工具文档决定了调用
gapi.client.*
对象下的哪一个服务
- 工具文档决定了调用
根据工具文档中的
resources
字段调用方法
加载gapi工具库
gapi === google application interface
<script src="https://apis.google.com/js/api.js"></script>
该工具库会全局注册gapi对象。
Notes: gapi的文档<<u>https://github.com/google/google-api-javascript-client/blob/master/docs/reference.md</u>>
加载授权模块
gapi.load("client:auth2", function() {
gapi.auth2.init({
client_id: CLIENTID,
// cookiepolicy: 'single_host_origin',
plugin_name: 'hello' // 必填,可以是任意值 —— 不填,会报错 {error: "popup_closed_by_user"}
});
});
登陆且授权
<button onclick="authenticate().then(loadClient)">authorize and load</button>
点击按钮后,授权服务,加载需要的服务API文档(gapi根据加载的文档会动态生成对应的服务方法)。
const scopes = [
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/drive.appdata",
"https://www.googleapis.com/auth/drive.file",
"https://www.googleapis.com/auth/drive.metadata",
"https://www.googleapis.com/auth/drive.metadata.readonly",
"https://www.googleapis.com/auth/drive.photos.readonly",
"https://www.googleapis.com/auth/drive.readonly"
] // 用户授权可访问的服务列表
function authenticate() {
return gapi.auth2.getAuthInstance()
.signIn({
scope: scopes.join(" ")
})
.then(
function() {
console.log("Sign-in successful");
},
function(err) {
console.error("Error signing in", err);
}
);
}
function loadClient() {
// 有了授权操作,就不需要设置ApiKey了,二者冲突<https://stackoverflow.com/questions/17436940/google-simple-api-key-stopped-working>
/**
* 以当前用户身份调取Api —— 使用access_token
* 以开发者身份调用API —— 使用API key
*/
// gapi.client.setApiKey(CLIENTSECRET);
return gapi.client.load("https://content.googleapis.com/discovery/v1/apis/drive/v3/rest")
.then(
function() {
console.log("GAPI client loaded for API");
},
function(err) {
console.error("Error loading GAPI client for API", err);
}
);
}
调用方法
<button onclick="execute()">execute</button>
直接浏览器打开https://content.googleapis.com/discovery/v1/apis/drive/v3/rest,查找对应的resources
字段,调用对应的methods
即可。
function execute() {
return gapi.client.drive.files.list({})
.then(
function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
},
function(err) {
console.error("Execute error", err);
}
);
}
完整代码
<!DOCTYPE html>
<html>
<head>
<title>Drive API Quickstart</title>
<meta charset="utf-8" />
</head>
<body>
<p>Drive API Quickstart</p>
<!--Add buttons to initiate auth sequence and sign out-->
<button onclick="authenticate().then(loadClient)">authorize and load</button>
<button onclick="execute()">execute</button>
<pre id="content"></pre>
<script src="https://apis.google.com/js/api.js"></script>
<script type="text/javascript">
const CLIENTID = '<your client_id>'
const CLIENTSECRET = '<your client_secret>'
const scopes = [
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/drive.appdata",
"https://www.googleapis.com/auth/drive.file",
"https://www.googleapis.com/auth/drive.metadata",
"https://www.googleapis.com/auth/drive.metadata.readonly",
"https://www.googleapis.com/auth/drive.photos.readonly",
"https://www.googleapis.com/auth/drive.readonly"
] // 用户授权可访问的服务列表
function authenticate() {
return gapi.auth2.getAuthInstance()
.signIn({
scope: scopes.join(" ")
})
.then(
function() {
console.log("Sign-in successful");
},
function(err) {
console.error("Error signing in", err);
}
);
}
function loadClient() {
// 有了授权操作,就不需要设置ApiKey了,二者冲突<https://stackoverflow.com/questions/17436940/google-simple-api-key-stopped-working>
/**
* 以当前用户身份调取Api —— 使用access_token
* 以开发者身份调用API —— 使用API key
*/
// gapi.client.setApiKey(CLIENTSECRET);
return gapi.client.load("https://content.googleapis.com/discovery/v1/apis/drive/v3/rest")
.then(
function() {
console.log("GAPI client loaded for API");
},
function(err) {
console.error("Error loading GAPI client for API", err);
}
);
}
// Make sure the client is loaded and sign-in is complete before calling this method.
function execute() {
return gapi.client.drive.files.list({})
.then(
function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
},
function(err) {
console.error("Execute error", err);
}
);
}
gapi.load("client:auth2", function() {
gapi.auth2.init({
client_id: CLIENTID,
// cookiepolicy: 'single_host_origin',
plugin_name: 'hello' // 必填,可以是任意值 —— 不填,会报错 {error: "popup_closed_by_user"}
});
});
</script>
</body>
</html>
Sample2:获取access_token
相关资源
<script async defer src="https://apis.google.com/js/api.js" onload="gapiLoaded()"></script>
<script async defer src="https://accounts.google.com/gsi/client" onload="gisLoaded()"></script>
获取用户实例
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: CLIENT_ID,
scope: SCOPES,
callback: '', // defined later
});
账号登陆检测
if (gapi.client.getToken() === null) {
// Prompt the user to select a Google Account and ask for consent to share their data
// when establishing a new session.
tokenClient.requestAccessToken({prompt: 'consent'});
} else {
// Skip display of account chooser and consent dialog for an existing session.
tokenClient.requestAccessToken({prompt: ''});
}
登陆后的回调
tokenClient.callback = async (resp) => {
if (resp.error !== undefined) {
throw (resp);
}
document.getElementById('signout_button').style.visibility = 'visible';
document.getElementById('authorize_button').innerText = 'Refresh';
await listFiles();
};
退出账号
const token = gapi.client.getToken();
if (token !== null) {
google.accounts.oauth2.revoke(token.access_token);
gapi.client.setToken('');
}
全部代码
<!DOCTYPE html>
<html>
<head>
<title>Drive API Quickstart</title>
<meta charset="utf-8" />
</head>
<body>
<p>Drive API Quickstart</p>
<!--Add buttons to initiate auth sequence and sign out-->
<button id="authorize_button" onclick="handleAuthClick()">Authorize</button>
<button id="signout_button" onclick="handleSignoutClick()">Sign Out</button>
<pre id="content"></pre>
<script type="text/javascript">
const CLIENT_ID = '<your-client_id>';
const API_KEY = '<your-api_key>';
const DISCOVERY_DOC = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';
const SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly';
let tokenClient;
let gapiInited = false;
let gisInited = false;
document.getElementById('authorize_button').style.visibility = 'hidden';
document.getElementById('signout_button').style.visibility = 'hidden';
function gapiLoaded() {
gapi.load('client', initializeGapiClient);
}
async function initializeGapiClient() {
await gapi.client.init({
discoveryDocs: [DISCOVERY_DOC],
});
gapiInited = true;
maybeEnableButtons();
}
function gisLoaded() {
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: CLIENT_ID,
scope: SCOPES,
callback: '', // defined later
});
gisInited = true;
maybeEnableButtons();
}
function maybeEnableButtons() {
if (gapiInited && gisInited) {
document.getElementById('authorize_button').style.visibility = 'visible';
}
}
function handleAuthClick() {
tokenClient.callback = async (resp) => {
if (resp.error !== undefined) {
throw (resp);
}
document.getElementById('signout_button').style.visibility = 'visible';
document.getElementById('authorize_button').innerText = 'Refresh';
await listFiles();
};
if (gapi.client.getToken() === null) {
// Prompt the user to select a Google Account and ask for consent to share their data
// when establishing a new session.
tokenClient.requestAccessToken({prompt: 'consent'});
} else {
// Skip display of account chooser and consent dialog for an existing session.
tokenClient.requestAccessToken({prompt: ''});
}
}
/**
* Sign out the user upon button click.
*/
function handleSignoutClick() {
const token = gapi.client.getToken();
if (token !== null) {
google.accounts.oauth2.revoke(token.access_token);
gapi.client.setToken('');
document.getElementById('content').innerText = '';
document.getElementById('authorize_button').innerText = 'Authorize';
document.getElementById('signout_button').style.visibility = 'hidden';
}
}
/**
* Print metadata for first 10 files.
*/
async function listFiles() {
let response;
try {
response = await gapi.client.drive.files.list({
'pageSize': 10,
'fields': 'files(id, name)',
});
} catch (err) {
document.getElementById('content').innerText = err.message;
return;
}
const files = response.result.files;
if (!files || files.length == 0) {
document.getElementById('content').innerText = 'No files found.';
return;
}
// Flatten to string to display
const output = files.reduce(
(str, file) => `${str}${file.name} (${file.id}\n`,
'Files:\n');
document.getElementById('content').innerText = output;
}
</script>
<script async defer src="https://apis.google.com/js/api.js" onload="gapiLoaded()"></script>
<script async defer src="https://accounts.google.com/gsi/client" onload="gisLoaded()"></script>
</body>
</html>
Sample3:创建文件
HTTP请求
Body的组装:
用自定义boundary
边界字符串标识每个部分,每部分都有两个连字符打头。
此外,在结束位置,仍以自定义boundary
边界字符串 + 两个连字符结尾。
async function upload () {
console.log('-------upload---token------', gapi.client.getToken())
let callback
var content = 'this is my secret'; // 新文件的正文
var blob = new Blob([content], { type: "text/plain"});
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
var reader = new FileReader();
reader.readAsBinaryString(blob);
reader.onload = function(e) {
var contentType = 'application/octet-stream';
var metadata = {
'name': 'aaa.txt',
'mimeType': contentType
};
var base64Data = btoa(reader.result);
var multipartRequestBody =
delimiter +
'Content-Type: application/json\r\n\r\n' +
JSON.stringify(metadata) +
delimiter +
'Content-Type: ' + contentType + '\r\n' +
'Content-Transfer-Encoding: base64\r\n' +
'\r\n' +
base64Data +
close_delim;
var request = gapi.client.request({
'path': '/upload/drive/v3/files',
'method': 'POST',
'params': {'uploadType': 'multipart'},
'headers': {
'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
},
'body': multipartRequestBody});
if (!callback) {
callback = function(file) {
console.log(file)
};
}
request.execute(callback);
}
}
axios请求
formData组装顺序:
Meatadata >> file
否则,会报错https://developers.google.com/drive/api/guides/manage-uploads#http_1。
var formData = new FormData();
var content = 'this is my secret'; // 新文件的正文
var blob = new Blob([content], { type: "text/plain"});
var metadata = {
'name': 'customfile.txt', // Filename at Google Drive
'mimeType': 'text/plain', // mimeType at Google Drive
// TODO [Optional]: Set the below credentials
// Note: remove this parameter, if no target is needed
// 'parents': ['SET-GOOGLE-DRIVE-FOLDER-ID'], // Folder ID at Google Drive which is optional
};
formData.append('metadata', new Blob([JSON.stringify(metadata)], { type: 'application/json' }));
formData.append("file", blob);
axios.post(
'https://www.googleapis.com/upload/drive/v3/files',
formData,
{
headers: {
Authorization: `Bearer ${access_token}`,
'Content-Type': 'multipart/form-data'
},
params: {
uploadType: 'multipart',
supportsAllDrives: true
},
}
)
Sample4: 创建文件夹
var parentId = '';//some parentId of a folder under which to create the new folder
var fileMetadata = {
'name' : 'New Folder',
'mimeType' : 'application/vnd.google-apps.folder',
'parents': [parentId]
};
gapi.client.drive.files.create({
resource: fileMetadata,
}).then(function(response) {
switch(response.status){
case 200:
var file = response.result;
console.log('Created Folder Id: ', file.id);
break;
default:
console.log('Error creating the folder, '+response);
break;
}
});
Sample5:读取文件内容
追加
?alt=media
可查看文件内容,否则,返回文件的metadata。
async function handleExport (_event: any, fileId = '') {
const res = await axios.get(
`https://www.googleapis.com/drive/v3/files/${fileId}`,
{
params: {
alt: 'media'
},
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
)
if (res.status === 200) {
return res.data
}
}
Sample6: 获取用户信息
查看用户所有信息,可传
fields: "*"
async function handleUserInfo () {
const res = await gapi.client.drive.about.get({
fields: "user, kind"
});
console.log('-------------uesr--------', res)
}
相关文档
Google-api-javascript客户端开发文档
Google Api指南
Google Drive File查询示例
Google Api Typescript类型声明