我正在将 Google Sheets API 用于将 Excel 工作表可视化为图表的 Web 应用程序。如果我在本地运行服务器并使用我的浏览器访问谷歌同意屏幕,这将非常有用......
但是,如果我将网页上传到我只有控制台访问权限的 linux 根服务器,我不能使用浏览器让机器访问 google api。
我使用 google api java 示例来编写此代码。
我现在的问题是:如何让我的网络服务器访问谷歌 API,我尝试了服务帐户,但是如果我使用从服务帐户获得的 json 作为客户端/秘密,它根本不起作用。
这是我的代码。也许这是一个简单的解决方法,我只是愚蠢地看到。
package de.promolitor.wabcodiagramviewer;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.sheets.v4.SheetsScopes;
import com.google.api.services.sheets.v4.model.*;
import com.google.gson.Gson;
import com.google.gson.JsonParser;
import de.promolitor.wabcodiagramviewer.data.DiagramNode;
import de.promolitor.wabcodiagramviewer.data.DiagramNodeTitles;
import de.promolitor.wabcodiagramviewer.data.WabcoExcelProperties;
import de.promolitor.wabcodiagramviewer.utils.SheetParsing;
import com.google.api.services.sheets.v4.Sheets;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
public class GoogleConnection {
/** Application name. */
private static final String APPLICATION_NAME = "Google Sheets API Java Quickstart";
/** Directory to store user credentials for this application. */
private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"),
".credentials/sheets.googleapis.com-java-quickstart");
/** Global instance of the {@link FileDataStoreFactory}. */
private static FileDataStoreFactory DATA_STORE_FACTORY;
/** Global instance of the JSON factory. */
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
/** Global instance of the HTTP transport. */
private static HttpTransport HTTP_TRANSPORT;
private static Sheets service;
/**
* Global instance of the scopes required by this quickstart.
*
* If modifying these scopes, delete your previously saved credentials at
* ~/.credentials/sheets.googleapis.com-java-quickstart
*/
private static final List<String> SCOPES = Arrays.asList(SheetsScopes.SPREADSHEETS_READONLY);
static {
try {
System.out.println("GoogleConnection: Absolut Path for Sheet API: " + DATA_STORE_DIR.getAbsolutePath());
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
} catch (Throwable t) {
t.printStackTrace();
System.exit(1);
}
}
/**
* Creates an authorized Credential object.
*
* @return an authorized Credential object.
* @throws IOException
*/
public static Credential authorize() throws IOException {
String relativeWebPath = "/resources/" + "client_secret.json";
ServletContext servletContext = (ServletContext) FacesContext.getCurrentInstance().getExternalContext()
.getContext();
String absoluteDiskPath = servletContext.getRealPath(relativeWebPath);
System.out.println("GoogleConnection: Absolut Path: " + absoluteDiskPath);
File file = new File(absoluteDiskPath);
InputStream in = new FileInputStream(file);
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY,
clientSecrets, SCOPES).setDataStoreFactory(DATA_STORE_FACTORY).setAccessType("offline").build();
Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
System.out.println("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
return credential;
}
/**
* Build and return an authorized Sheets API client service.
*
* @return an authorized Sheets API client service
* @throws IOException
*/
public static Sheets getSheetsService() throws IOException {
Credential credential = authorize();
return new Sheets.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME)
.build();
}
public static void initializeSheetService() throws IOException {
service = getSheetsService();
}
public static List<WabcoExcelProperties> getSheetsData(String Id) throws IOException {
System.out.println("GoogleConnection: Loading sheetData for SheetNames!");
Spreadsheet responseSheet = null;
try {
responseSheet = service.spreadsheets().get(Id).execute();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
List<Sheet> values = responseSheet.getSheets();
List<WabcoExcelProperties> sheetData = new ArrayList<WabcoExcelProperties>();
JsonParser jp = new JsonParser();
Gson gson = new Gson();
for (Sheet sheet : values) {
sheetData.add(gson.fromJson(jp.parse(sheet.get("properties").toString()), WabcoExcelProperties.class));
}
System.out.println("GoogleConnection: Loading sheetData for SheetNames! COMPLETE");
return sheetData;
}
public static List<DiagramNode> getDiagramNodeInformation(String spreadsheetId, String range, String sheetName)
throws IOException {
System.out.println("GoogleConnection: PARSING DIAGRAM NODE INFORMATION");
List<DiagramNode> nodes = new ArrayList<DiagramNode>();
ValueRange response = service.spreadsheets().values().get(spreadsheetId, range).execute();
List<List<Object>> values = response.getValues();
try {
System.out.println("GoogleConnection: Trying to load titles!");
List<Object> data = values.get(0);
FacesContext context = FacesContext.getCurrentInstance();
DiagramNodeTitles dnt = context.getApplication().evaluateExpressionGet(context, "#{diagramNodeTitles}",
DiagramNodeTitles.class);
dnt.setNeworder((String) data.get(SheetParsing.NEWORDER));
dnt.setPa((String) data.get(SheetParsing.PA));
dnt.setPb((String) data.get(SheetParsing.PB));
dnt.setPc((String) data.get(SheetParsing.PC));
dnt.setPd((String) data.get(SheetParsing.PD));
dnt.setKeytask((String) data.get(SheetParsing.KEYTASK));
dnt.setPhase((String) data.get(SheetParsing.PHASE));
dnt.setPrecedentstep((String) data.get(SheetParsing.PRECEDENTSTEP));
dnt.setId((String) data.get(SheetParsing.ID));
dnt.setType((String) data.get(SheetParsing.TYPE));
dnt.setTask((String) data.get(SheetParsing.TASK));
dnt.setDeliverable((String) data.get(SheetParsing.DELIVERABLE));
dnt.setRole((String) data.get(SheetParsing.ROLE));
dnt.setApqelement((String) data.get(SheetParsing.APQPELEMENT));
dnt.setSuppliers((String) data.get(SheetParsing.SUPPLIERS));
dnt.setInput((String) data.get(SheetParsing.INPUT));
dnt.setProcessdescription((String) data.get(SheetParsing.PROCESSDESCRIPTION));
dnt.setOutput((String) data.get(SheetParsing.OUTPUT));
dnt.setCustomer((String) data.get(SheetParsing.CUSTOMER));
dnt.setR((String) data.get(SheetParsing.R));
dnt.setA((String) data.get(SheetParsing.A));
dnt.setS((String) data.get(SheetParsing.S));
dnt.setC((String) data.get(SheetParsing.C));
dnt.setI((String) data.get(SheetParsing.I));
dnt.setDeliverabletemplate((String) data.get(SheetParsing.DELIVERABLETEMPLATE));
dnt.setWorkinstruction((String) data.get(SheetParsing.WORKINSTRUCTION));
dnt.setBestpractice((String) data.get(SheetParsing.BESTPRACTICE));
dnt.setUsefullinks((String) data.get(SheetParsing.USEFULLINKLS));
System.out.println("GoogleConnection: LOADING TITLES COMPLETE");
} catch (Exception e) {
System.out.println("GoogleConnection: ERROR WHILE LOADING TITLES");
e.printStackTrace();
}
for (int i = 1; i < values.size() - 1; i++) {
try {
List<Object> data = values.get(i);
System.out.println("GoogleConnection: Parsing Row" + (i + 1) + " Row Size: " + data.size());
String Id = (String) data.get(SheetParsing.ID);
double newOrderCell = Double.parseDouble((String) data.get(SheetParsing.NEWORDER));
if (newOrderCell == 0.0 || ((String) data.get(SheetParsing.TYPE)).equals("delete")
|| ((String) data.get(SheetParsing.ID)).startsWith("<")) {
if (newOrderCell == 0.0)
System.out.println("New Order Cell == 0");
if (((String) data.get(SheetParsing.TYPE)).equals("delete"))
System.out.println("cell should be deleted...");
if (((String) data.get(SheetParsing.ID)).startsWith("<"))
System.out.println("Cell starts with <... so we do not care.");
continue;
}
if (DataManager.debug)
System.out.println("Adding NewOrder: " + newOrderCell);
int phase = 0;
int newOrder = 0;
try {
phase = Integer.parseInt(((String) data.get(SheetParsing.PHASE)));
newOrder = Integer.parseInt(((String) data.get(SheetParsing.NEWORDER)));
} catch (NumberFormatException e) {
}
boolean PA = false;
boolean PB = false;
boolean PC = false;
boolean PD = false;
boolean KEYTASK = false;
String PRECEDENTSTEP = "";
String ID = "";
String TYPE = "";
String TASK = "";
String ROLE = "";
String APQPELEMENT = "";
String SUPPLIERS = "";
String INPUT = "";
String PROCESSDESCRIPTION = "";
String OUTPUT = "";
String CUSTOMER = "";
String R = "";
String A = "";
String S = "";
String C = "";
String I = "";
String DELIVERABLETEMPLATE = "";
String WORKINSTRUCTION = "";
String BESTPRACTICE = "";
String USEFULLINKS = "";
try {
PA = ((String) data.get(SheetParsing.PA)).toLowerCase().contains("x");
PB = ((String) data.get(SheetParsing.PB)).toLowerCase().contains("x");
PC = ((String) data.get(SheetParsing.PC)).toLowerCase().contains("x");
PD = ((String) data.get(SheetParsing.PD)).toLowerCase().contains("x");
KEYTASK = ((String) data.get(SheetParsing.KEYTASK)).toLowerCase().contains("x");
PRECEDENTSTEP = ((String) data.get(SheetParsing.PRECEDENTSTEP));
ID = ((String) data.get(SheetParsing.ID));
TYPE = ((String) data.get(SheetParsing.TYPE));
TASK = ((String) data.get(SheetParsing.TASK));
ROLE = ((String) data.get(SheetParsing.ROLE));
APQPELEMENT = ((String) data.get(SheetParsing.APQPELEMENT));
SUPPLIERS = ((String) data.get(SheetParsing.SUPPLIERS));
INPUT = ((String) data.get(SheetParsing.INPUT));
PROCESSDESCRIPTION = ((String) data.get(SheetParsing.PROCESSDESCRIPTION));
OUTPUT = ((String) data.get(SheetParsing.OUTPUT));
CUSTOMER = ((String) data.get(SheetParsing.CUSTOMER));
R = ((String) data.get(SheetParsing.R));
A = ((String) data.get(SheetParsing.A));
S = ((String) data.get(SheetParsing.S));
C = ((String) data.get(SheetParsing.C));
I = ((String) data.get(SheetParsing.I));
DELIVERABLETEMPLATE = ((String) data.get(SheetParsing.DELIVERABLETEMPLATE));
WORKINSTRUCTION = ((String) data.get(SheetParsing.WORKINSTRUCTION));
BESTPRACTICE = ((String) data.get(SheetParsing.BESTPRACTICE));
USEFULLINKS = (String) data.get(SheetParsing.USEFULLINKLS);
} catch (IndexOutOfBoundsException e) {
}
DiagramNode node = new DiagramNode(sheetName, newOrder, PA, PB, PC, PD, KEYTASK, phase, PRECEDENTSTEP,
ID, TYPE, TASK, ROLE, APQPELEMENT, SUPPLIERS, INPUT, PROCESSDESCRIPTION, OUTPUT, CUSTOMER, R, A,
S, C, I, DELIVERABLETEMPLATE, WORKINSTRUCTION, BESTPRACTICE, USEFULLINKS);
System.out.println("GoogleConnection: Adding Node: " + node);
nodes.add(node);
} catch (Exception e) {
System.out.println("GoogleConnection: ERROR IN ROW.");
e.printStackTrace();
}
}
System.out.println("GoogleConnection: Create Node: " + nodes);
return nodes;
}
// public static void main(String[] args) throws IOException {
// // Build a new authorized API client service.
// initializeSheetService();
//
// List<WabcoExcelProperties> sheetData =
// getSheetsData(SheetParsing.SPREADSHEETID);
// System.out.println(sheetData.get(1).getTitle());
//
// }
}
更新 错误是:“未授权”
经过几个小时的故障排除后,我终于设法解决了它。我尝试了很多 p12 密钥文件和“Google 服务帐户”,但这似乎也没有用。我也一直得到“未授权”。
我之前尝试过使用完整 json 文件的服务帐户。至少我觉得...
当我第二次改变它时,我必须有不同的模式。
我补充说:
GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream(absoluteDiskPathToJson)).createScoped(SCOPES);
//Added the sheets with credentials.
Sheets sheets = Sheets.Builder(httpTransport, JSON_FACTORY, credential).build();
这以某种方式起作用。我确定我之前已经尝试过使用 json 文件 + 服务帐户,但我可能在某个地方犯了一个小错误。我还尝试将我的主帐户的访问权限传递给服务帐户,这也不起作用,或者我在某个地方出错了。我现在也向服务帐户添加了所需的访问权限。经过 12 小时的故障排除后,它现在可以正常工作了。