Sample1:授權(quán)
概述
主要分為五步:
加載api工具庫
登陸
scopes授權(quán)
-
加載對應(yīng)的工具文檔
- 工具文檔決定了調(diào)用
gapi.client.*
對象下的哪一個(gè)服務(wù)
- 工具文檔決定了調(diào)用
根據(jù)工具文檔中的
resources
字段調(diào)用方法
加載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>>
加載授權(quán)模塊
gapi.load("client:auth2", function() {
gapi.auth2.init({
client_id: CLIENTID,
// cookiepolicy: 'single_host_origin',
plugin_name: 'hello' // 必填,可以是任意值 —— 不填忌警,會報(bào)錯(cuò) {error: "popup_closed_by_user"}
});
});
登陸且授權(quán)
<button onclick="authenticate().then(loadClient)">authorize and load</button>
點(diǎn)擊按鈕后刨秆,授權(quán)服務(wù),加載需要的服務(wù)API文檔(gapi根據(jù)加載的文檔會動(dòng)態(tài)生成對應(yīng)的服務(wù)方法)辆脸。
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"
] // 用戶授權(quán)可訪問的服務(wù)列表
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() {
// 有了授權(quán)操作臂聋,就不需要設(shè)置ApiKey了告材,二者沖突<https://stackoverflow.com/questions/17436940/google-simple-api-key-stopped-working>
/**
* 以當(dāng)前用戶身份調(diào)取Api —— 使用access_token
* 以開發(fā)者身份調(diào)用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);
}
);
}
調(diào)用方法
<button onclick="execute()">execute</button>
直接瀏覽器打開https://content.googleapis.com/discovery/v1/apis/drive/v3/rest事镣,查找對應(yīng)的resources
字段步鉴,調(diào)用對應(yīng)的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" style="white-space: pre-wrap;"></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"
] // 用戶授權(quán)可訪問的服務(wù)列表
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() {
// 有了授權(quán)操作璃哟,就不需要設(shè)置ApiKey了氛琢,二者沖突<https://stackoverflow.com/questions/17436940/google-simple-api-key-stopped-working>
/**
* 以當(dāng)前用戶身份調(diào)取Api —— 使用access_token
* 以開發(fā)者身份調(diào)用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' // 必填,可以是任意值 —— 不填随闪,會報(bào)錯(cuò) {error: "popup_closed_by_user"}
});
});
</script>
</body>
</html>
Sample2:獲取access_token
相關(guān)資源
<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>
獲取用戶實(shí)例
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: ''});
}
登陸后的回調(diào)
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" style="white-space: pre-wrap;"></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:創(chuàng)建文件
HTTP請求
Body的組裝:
用自定義boundary
邊界字符串標(biāo)識每個(gè)部分艺沼,每部分都有兩個(gè)連字符打頭。
此外蕴掏,在結(jié)束位置,仍以自定義boundary
邊界字符串 + 兩個(gè)連字符結(jié)尾调鲸。
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
否則盛杰,會報(bào)錯(cuò)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: 創(chuàng)建文件夾
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:讀取文件內(nèi)容
追加
?alt=media
可查看文件內(nèi)容藐石,否則即供,返回文件的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)
}