使用Google Sheets API v4访问公共Google Spreadsheet时发生PERMISSION_DENIED错误

时间:2018-07-18 13:32:23

标签: google-sheets-api

在我的Web应用程序中,直到现在,我都可以使用以下HTML / JavaScript代码完全访问公开的Google Spreadsheet:

HTML

<script src="https://apis.google.com/js/client.js?onload=loadSheetsApi"></script>

JavaScript

function loadSheetsApi() {
  gapi.client.setApiKey('<<MY_API_KEY>>');
  var discoveryUrl =
    'https://sheets.googleapis.com/$discovery/rest?version=v4';
  gapi.client.load(discoveryUrl).then(<<MY_FUNCTION>>);
}

即使我没有更改HTML或JavaScript,该请求仍返回以下

错误消息

{
  "error": {
    "code": 403,
    "message": "The caller does not have permission",
    "status": "PERMISSION_DENIED"
  }
}

不能使用OAuth,因为我正在网站上显示电子表格数据。

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

昨天我遇到了同样的问题,我发现的唯一解决方案是创建服务帐户,并与文档共享提供的电子邮件,并更改代码以获取数据。在我的情况下,您需要将工作表数据与Web服务器中的某个文件夹同步。如果需要的话,我给您留下了python代码。

import argparse
import sys
import json
import os

from google.oauth2 import service_account
import googleapiclient.discovery

reload(sys)
sys.setdefaultencoding('UTF8')

SCOPES = [
    'https://www.googleapis.com/auth/spreadsheets.readonly',
    'https://www.googleapis.com/auth/spreadsheets',
    'https://www.googleapis.com/auth/drive.readonly',
    'https://www.googleapis.com/auth/drive.file',
    'https://www.googleapis.com/auth/drive'
]

SERVICE_ACCOUNT_FILE = './service.json'

credentials = service_account.Credentials.from_service_account_file(
    SERVICE_ACCOUNT_FILE, scopes=SCOPES)

service = googleapiclient.discovery.build('sheets', 'v4', credentials=credentials)

def save_file(filename, path, data, header):
    absolute_filename = (path + '/' + filename)
    if not header:
        absolute_filename = path + '/sheets/' + filename
        print "Trying " + absolute_filename
        directory = os.path.dirname(absolute_filename)
        try:
            os.stat(directory)
        except:
            os.makedirs(directory)

        with open(absolute_filename, 'w+') as outfile:
           json.dump(data, outfile)

def get_data(spreadsheet_id, row_range):
    if row_range is None:
        request = service.spreadsheets().get(spreadsheetId=spreadsheet_id)        
    else:
        request = service.spreadsheets().values().get(spreadsheetId=spreadsheet_id, range=row_range)
    return request.execute()

def download_spreadsheet(args):
    spreadsheet_id = args.spreadsheetId
    output_path = args.outputPath
    head = get_data(spreadsheet_id, None)
    save_file(spreadsheet_id, output_path, head, True)
    detail = head['sheets']
    for sheet in detail:
        if 'GRID' == sheet['properties']['sheetType']:
            sheet_name = sheet['properties']['title']
            row_range = sheet_name + "!A1:AZ10000"
            data = get_data(spreadsheet_id, row_range)
            save_file(sheet_name, output_path, data, True)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Download google sheet from api as JSON')
    parser.add_argument('--spreadsheet-id', metavar='Your SPREADSHEET ID', dest='spreadsheetId', required=True,
                    help='Your Google\'s SpreadSheet Id')
    parser.add_argument('--output-path', metavar='Output directory', dest='outputPath', required=True,
                    help='Output path')
    download_spreadsheet(parser.parse_args())