Google Development Api功能開發(fā)使用示例

Sample1:授權(quán)

概述

主要分為五步:

  1. 加載api工具庫

  2. 登陸

  3. scopes授權(quán)

  4. 加載對應(yīng)的工具文檔

    • 工具文檔決定了調(diào)用gapi.client.*對象下的哪一個(gè)服務(wù)
  5. 根據(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)
}

相關(guān)文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末逗嫡,一起剝皮案震驚了整個(gè)濱河市青自,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌驱证,老刑警劉巖延窜,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異抹锄,居然都是意外死亡逆瑞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進(jìn)店門伙单,熙熙樓的掌柜王于貴愁眉苦臉地迎上來获高,“玉大人,你說我怎么就攤上這事吻育∧钛恚” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵布疼,是天一觀的道長摊趾。 經(jīng)常有香客問我,道長缎除,這世上最難降的妖魔是什么严就? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮器罐,結(jié)果婚禮上梢为,老公的妹妹穿的比我還像新娘。我一直安慰自己轰坊,他們只是感情好铸董,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著肴沫,像睡著了一般粟害。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上颤芬,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天悲幅,我揣著相機(jī)與錄音,去河邊找鬼站蝠。 笑死汰具,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的菱魔。 我是一名探鬼主播留荔,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼澜倦!你這毒婦竟也來了聚蝶?” 一聲冷哼從身側(cè)響起杰妓,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎碘勉,沒想到半個(gè)月后巷挥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恰聘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年句各,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晴叨。...
    茶點(diǎn)故事閱讀 40,146評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凿宾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出兼蕊,到底是詐尸還是另有隱情初厚,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布孙技,位于F島的核電站产禾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏牵啦。R本人自食惡果不足惜亚情,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望哈雏。 院中可真熱鬧楞件,春花似錦、人聲如沸裳瘪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彭羹。三九已至黄伊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間派殷,已是汗流浹背还最。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留毡惜,地道東北人憋活。 一個(gè)月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像虱黄,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子吮成,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內(nèi)容