Средство выбора файлов Google + файл drive.file - PullRequest
0 голосов
/ 26 мая 2020

В рамках проекта Strobe Google планирует перевести многие области API Google Диска в «ограниченные», что означает, что вам потребуется независимая проверка безопасности.

В той же статье они предлагают использовать Средство выбора Google и область drive.file для получения доступа к каждому файлу. Я успешно реализовал API Google Picker для доступа к файлам и получения метаданных файла. Но как мне на самом деле импортировать содержимое файла с помощью этого потока (например, данные в реальном листе Google)?

GOOGLE PICKER WRAPPER

import React from "react";
import PropTypes from "prop-types";
import loadScript from "load-script";

const GOOGLE_SDK_URL = "https://apis.google.com/js/api.js";

let scriptLoadingStarted = false;

class GoogleFilePicker extends React.Component {
  static propTypes = {
    children: PropTypes.node,
    clientId: PropTypes.string.isRequired,
    developerKey: PropTypes.string,
    scope: PropTypes.array,
    viewId: PropTypes.string,
    authImmediate: PropTypes.bool,
    origin: PropTypes.string,
    onChange: PropTypes.func,
    onAuthenticate: PropTypes.func,
    onAuthFailed: PropTypes.func,
    createPicker: PropTypes.func,
    multiselect: PropTypes.bool,
    navHidden: PropTypes.bool,
    disabled: PropTypes.bool,
    authToken: PropTypes.string,
  };

  static defaultProps = {
    onChange: () => {},
    onAuthenticate: () => {},
    onAuthFailed: () => {},
    scope: ["https://www.googleapis.com/auth/drive.file"],
    viewId: "DOCS",
    authImmediate: false,
    multiselect: false,
    navHidden: false,
    disabled: false,
    authToken: "",
  };

  constructor(props) {
    super(props);

    this.onApiLoad = this.onApiLoad.bind(this);
    this.onChoose = this.onChoose.bind(this);
  }

  componentDidMount() {
    if (this.isGoogleReady()) {
      // google api is already exists
      // init immediately
      this.onApiLoad();
    } else if (!scriptLoadingStarted) {
      // load google api and the init
      scriptLoadingStarted = true;
      loadScript(GOOGLE_SDK_URL, this.onApiLoad);
    } else {
      // is loading
    }
  }

  isGoogleReady() {
    return !!window.gapi;
  }

  isGoogleAuthReady() {
    return !!window.gapi.auth;
  }

  isGooglePickerReady() {
    return !!window.google.picker;
  }

  onApiLoad() {
    window.gapi.load("auth");
    window.gapi.load("picker");
  }

  doAuth(callback) {
    window.gapi.auth.authorize(
      {
        client_id: this.props.clientId,
        scope: this.props.scope,
        immediate: this.props.authImmediate,
      },
      callback
    );
  }

  onChoose() {
    if (
      !this.isGoogleReady() ||
      !this.isGoogleAuthReady() ||
      !this.isGooglePickerReady() ||
      this.props.disabled
    ) {
      return null;
    }

    // const token = window.gapi.auth.getToken();
    // const oauthToken = token && token.access_token;
    const oauthToken = this.props.authToken;

    if (oauthToken) {
      this.createPicker(oauthToken);
    } else {
      this.doAuth((response) => {
        if (response.access_token) {
          this.createPicker(response.access_token);
        } else {
          this.props.onAuthFailed(response);
        }
      });
    }
  }

  createPicker(oauthToken) {
    // this.props.onAuthenticate(oauthToken);

    if (this.props.createPicker) {
      return this.props.createPicker(window.google, oauthToken);
    }

    const googleViewId = window.google.picker.ViewId[this.props.viewId];
    const view = new window.google.picker.View(googleViewId);

    if (this.props.mimeTypes) {
      view.setMimeTypes(this.props.mimeTypes.join(","));
    }
    if (this.props.query) {
      view.setQuery(this.props.query);
    }

    if (!view) {
      throw new Error("Can't find view by viewId");
    }

    const picker = new window.google.picker.PickerBuilder()
      .addView(view)
      .setOAuthToken(oauthToken)
      .setDeveloperKey(this.props.developerKey)
      .setCallback(this.props.onChange);

    if (this.props.origin) {
      picker.setOrigin(this.props.origin);
    }

    if (this.props.navHidden) {
      picker.enableFeature(window.google.picker.Feature.NAV_HIDDEN);
    }

    if (this.props.multiselect) {
      picker.enableFeature(window.google.picker.Feature.MULTISELECT_ENABLED);
    }

    picker.build().setVisible(true);
  }

  render() {
    console.log(window.gapi);
    return (
      <div onClick={this.onChoose}>
        {this.props.children ? (
          this.props.children
        ) : (
          <button>Open google chooser</button>
        )}
      </div>
    );
  }
}

export default GoogleFilePicker;

ВЫЗОВ ОБОЛОЧКИ

Я вызываю компонент выше в приведенном ниже коде. После получения документа я вызываю функцию copyFile. Эта функция работает должным образом, если документ был создан приложением, но не когда файл был создан пользователем вне приложения. Я знаю, что это предназначено Google для области drive.google.file, но в документации подразумевается, что использование Google Picker должно решить эту проблему. Не могли бы вы уточнить?

  <GoogleFilePicker
    clientId="CLIENT ID"
    developerKey="DEVELOPER KEY"
    scope={["https://www.googleapis.com/auth/drive.file"]}
    onChange={(data) => {
      if (data.docs) {
        copyFile(data.docs[0].id, `Template: ${data.docs[0].name}`, "");
      }
    }}
    onAuthenticate={(token) => console.log("oauth token:", token)}
    onAuthFailed={(data) => console.log("on auth failed:", data)}
    multiselect={true}
    navHidden={true}
    authImmediate={false}
    // mimeTypes={["image/png", "image/jpeg", "image/jpg"]}
    viewId={"DOCS"}
    authToken={auth.state.user.googleToken}
  >
...