我正在尝试使用Google Drive Java API v3为我们的应用程序实施一项新服务,该服务负责将文件上传到Google Team Drive中的特定文件夹。我使用公司专门为此项目创建的服务帐户,并且还从Google Developer Console生成了一个包含私钥的JSON文件。我还使用电子邮件xxxxx@xxxx.iam.gserviceaccount.com将文件夹共享到服务帐户,并将Content Manager的权限授予了共享的Team Drive。此外,出于某些原因,未授予该服务帐户整个G Suite范围的权限。
我要在这里实现什么?
我想使用服务帐户生成的私钥构建并返回授权的Google Drive客户服务,因此能够发送将文件上传到Google Team Drive中的文件夹的请求。
我目前使用的是什么
出了什么问题?
我无法成功退回授权的Google云端硬盘客户端服务,并且根本没有发送上传文件的请求。更令人困惑的是,没有引发异常。但是,将成功返回带有访问令牌和到期时间的凭据。
我已经阅读/发现的内容:
将OAuth2.0用于服务器到服务器应用程序:https://developers.google.com/identity/protocols/OAuth2ServiceAccount
有关创建对Drive API的简单请求的Java快速入门: https://developers.google.com/drive/api/v3/quickstart/java
Drive API的JavaDoc参考: https://developers.google.com/resources/api-libraries/documentation/drive/v3/java/latest/
如何使用服务帐户凭据将文件上传到Google驱动器: How to upload file to google drive with service account credential
如何使用带有Google Drive .NET API v3的服务帐户访问Team Drive: How to access Team Drive using service account with Google Drive .NET API v3
使用Java的Google驱动器API客户端库进行身份验证以上传驱动器中的文件 Authentication to upload files in my drive using Google drive API client library for Java
我已经尝试过的内容:
ContractStateUpdateService.java的相关部分:
File fileMetadata = new File();
fileMetadata.setName(fileTitle);
// setting the id of folder to which the file must be inserted to
fileMetadata.setParents(Collections.singletonList("dumbFolderId"));
fileMetadata.setMimeType("application/pdf");
byte[] pdfBytes = Base64.getDecoder().decode(base64File.getBytes(StandardCharsets.UTF_8));
InputStream inputStream = new ByteArrayInputStream(pdfBytes);
// decoding base64 to PDF and its contents to a byte array without saving the file on the file system
InputStreamContent mediaContent = new InputStreamContent("application/pdf", inputStream);
logger.info("Starting to send the request to drive api");
File file = DriveUtils.getDriveService().files().create(fileMetadata, mediaContent).execute();
logger.info("Succesfully uploaded file: " + file.getDriveId());
DriveUtils.java:
public class DriveUtils {
private static final String APPLICATION_NAME = "Google Drive Service";
// setting the Drive scope since it is essential to access Team Drive
private static List<String> SCOPES = Collections.singletonList(DriveScopes.DRIVE);
// private key is stored at the root of the project for now
private static String PRIVATE_KEY_PATH = "/path/to/private_key.json";
private static final Logger logger = LoggerFactory.getLogger(DriveUtils.class);
// build and return an authorized drive client service
public static Drive getDriveService() throws IOException, GeneralSecurityException {
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredentials credentials;
try (FileInputStream inputStream = new FileInputStream(PRIVATE_KEY_PATH)){
credentials = ServiceAccountCredentials.fromStream(inputStream).createScoped(SCOPES);
credentials.refreshIfExpired();
AccessToken token = credentials.getAccessToken();
logger.info("credentials: " + token.getTokenValue());
} catch (FileNotFoundException ex) {
logger.error("File not found: {}", PRIVATE_KEY_PATH);
throw new FileNotFoundException("File not found: " + ex.getMessage());
}
logger.info("Instantiating client next");
// Instantiating a client: this is where the client should be built but nothing happens... no exceptions!
Drive service = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, (HttpRequestInitializer) credentials)
.setApplicationName(APPLICATION_NAME)
.build();
// this log should appear immediately after the client has been instantiated but still nothing happens
logger.info("Client instantiated");
return service;
}
}
pom.xml:
<!-- https://mvnrepository.com/artifact/com.google.api-client/google-api-client -->
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.29.2</version>
</dependency>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-drive</artifactId>
<version>v3-rev165-1.25.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.auth/google-auth-library-oauth2-http -->
<dependency>
<groupId>com.google.auth</groupId>
<artifactId>google-auth-library-oauth2-http</artifactId>
<version>0.16.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security.oauth/spring-security-oauth2 -->
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.oauth-client/google-oauth-client-jetty -->
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId>
<version>1.29.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
我确定我在这里遗漏了一些东西,我事先为我的英语道歉。任何帮助将不胜感激。
答案 0 :(得分:0)
谢谢您的评论,这里的建议很有帮助,值得研究。但是,我将在此处介绍的解决方案无法直接回答有关我的代码如何或为什么不产生任何错误消息的问题。因此,现在,这是我针对该问题的解决方法:
pom.xml:
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.23.0</version>
</dependency>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-drive</artifactId>
<version>v3-rev110-1.23.0</version>
</dependency>
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId>
<version>1.23.0</version>
</dependency>
setSupportsTeamDrive
的值设置为true。如果没有该属性,我们将根本无法将文件保存到Team Drive的共享文件夹中。ContractStateUpdateService.java:
File fileMetadata = new File();
fileMetadata.setName(fileTitle);
// setting the id of folder to which the file must be inserted to
fileMetadata.setParents(Collections.singletonList("dumbTeamDriveId"));
fileMetadata.setMimeType("application/pdf");
// decoding base64 to PDF and its contents to a byte array without saving the file on the file system
byte[] pdfBytes = Base64.getDecoder().decode(base64File.getBytes(StandardCharsets.UTF_8);
InputStream inputStream = new ByteArrayInputStream(pdfBytes);
InputStreamContent mediaContent = new InputStreamContent("application/pdf", inputStream);
try {
// upload updated agreement as a PDF file to the Team Drive folder
DriveUtils.getDriveService().files().create(fileMetadata, mediaContent)
.setSupportsTeamDrives(true) // remember to set this property to true!
.execute();
} catch (IOException ex) {
logger.error("Exception: {}", ex.getMessage());
throw new IOException("Exception: " + ex.getMessage());
} catch (GeneralSecurityException ex) {
logger.error("Exception: {}", ex.getMessage());
throw new GeneralSecurityException("Exception: " + ex.getMessage());
}
来自 DriveUtils-class 的更新代码:
// create and return credential
private static Credential getCredentials() throws IOException {
GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream(PRIVATE_KEY_PATH))
.createScoped(SCOPES);
return credential;
}
// build and return an authorized drive client service
public static Drive getDriveService() throws IOException, GeneralSecurityException {
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
// Instantiating a client
Drive service = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials())
.setApplicationName(APPLICATION_NAME)
.build();
return service;
}