Google云端存储 - com.google.appengine.api.appidentity.AppIdentityServiceFailureException

时间:2016-09-04 10:30:36

标签: google-app-engine google-cloud-storage

我正在尝试使用在Google App Engine中运行的jaxrs服务将文件存储到Google云端存储。在尝试存储文件时,我遇到了错误。

com.google.appengine.tools.cloudstorage.NonRetriableException:com.google.appengine.api.appidentity.AppIdentityServiceFailureException:AppIdentity服务引发了意外错误。详情:

我正在尝试将文件保存到新存储桶,并为存储桶提供以下ID(计算,应用引擎和服务帐户)权限。我还创建了一个单独的服务帐户,并为此服务帐户提供了Writer权限(此帐户的编辑角色为项目)

  • myaccount@myproject.iam.gserviceaccount.com
  • xxxx-compute@developer.gserviceaccount.com
  • xxxx@cloudservices.gserviceaccount.com

我理解不需要服务帐户,因为从具有默认服务的应用引擎我们应该能够存储该文件。但只是为了尝试我也创建了上面的服务帐户并将文件存储在WEB-INF / resources / service_account_credentials.json位置,并在appengine-web.xml中设置以下属性

<property name="GOOGLE_APPLICATION_CREDENTIALS" value="WEB-INF/resources/service_account_credentials.json"/>

我尝试了以下两种存储文件的方法,但两者都给出了错误。

第一种方式......

获得服务

    GcsService gcsService = GcsServiceFactory.createGcsService(new RetryParams.Builder()
          .initialRetryDelayMillis(10)
          .retryMaxAttempts(10)
          .totalRetryPeriodMillis(15000)
          .build());

存储文件

  GcsFileOptions  gcsFileOptions = null ;
  GcsFileOptions.Builder builder = new GcsFileOptions.Builder() ;
  if(aclEntityName != null)
      builder = builder.acl(aclEntityName) ;


  if(fileMetaData != null && !fileMetaData.isEmpty())
  for(Map.Entry<String, String> entry : fileMetaData.entrySet()){
      builder = builder.addUserMetadata(entry.getKey(), entry.getValue()) ;
  }
  gcsFileOptions = builder.build() ;
  GcsFilename fileName = new GcsFilename(bucketName, name) ;
  GcsService gcsService = StorageFactory.getGcsService() ;
  GcsOutputChannel outputChannel = gcsService.createOrReplace(fileName, gcsFileOptions);
  copy(contentStream, Channels.newOutputStream(outputChannel));

下面给出的第二种方法也会出现同样的错误......

获得服务

HttpTransport transport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = 
GoogleCredential.getApplicationDefault(transport, jsonFactory);
if (credential.createScopedRequired()) {
      Collection<String> scopes = StorageScopes.all();
      credential = credential.createScoped(scopes);
    }
    return new Storage.Builder(transport, jsonFactory, credential)
            .setApplicationName("GCS Samples")
            .build();

以第二种方式存储文件

StorageObject objectMetaData = new StorageObject();
objectMetaData.setName(name);

if(fileMetaData != null && fileMetaData.isEmpty() == false )
    objectMetaData.setMetadata(fileMetaData) ;

    // Set the access control list to publicly read-only

if(aclEntityName != null && !aclEntityName.trim().equals("")
    && aclRole != null && !aclRole.trim().equals("") ) {
    objectMetaData.setAcl(Arrays.asList(
        new ObjectAccessControl().setEntity(aclEntityName).setRole(aclRole)));
}

InputStreamContent mediaContent = new InputStreamContent("application/octet-stream", contentStream);


// Do the insert
Storage client = StorageFactory.getService();
Storage.Objects.Insert insertRequest = client.objects().insert(
        bucketName, objectMetaData, mediaContent);    
if (mediaContent.getLength() > 0 && mediaContent.getLength() <= 2 * 1000 * 1000 /* 2MB */) {
    insertRequest.getMediaHttpUploader().setDirectUploadEnabled(true);
    }
insertRequest.execute();

我做错了什么?我有什么设置来修复此错误吗?请帮忙!!!

1 个答案:

答案 0 :(得分:0)

根据我对Google Application Default Credentials的理解,使用GOOGLE_APPLICATION_CREDENTIALS环境变量应该指向本地文件,并且通常与gcloud命令行工具一起用于在本地测试代码时进行身份验证。 / p>

据说https://stackoverflow.com/a/36408645/374638,或许这应该在<env-variables>中。