【问题标题】:Google Cloud Storage - com.google.appengine.api.appidentity.AppIdentityServiceFailureException谷歌云存储 - com.google.appengine.api.appidentity.AppIdentityServiceFailureException
【发布时间】:2017-01-11 23:03:54
【问题描述】:

我正在尝试使用在 Google App Engine 中运行的 jaxrs 服务将文件存储到 Google Cloud Storage。尝试存储文件时出现以下错误。

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();

我做错了什么?我需要做任何设置来修复此错误吗?请帮忙!!!

【问题讨论】:

  • 异常是否提供更多详细信息(在“详细信息:”之后)?如果是这样,请将其包含在您的问题中。
  • 不,Details前面没有任何信息。只是一个空格。

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


【解决方案1】:

根据我对Google Application Default Credentials的理解,使用GOOGLE_APPLICATION_CREDENTIALS环境变量应该是指向本地文件,在本地测试代码时一般配合gcloud命令行工具进行身份验证。

也就是说,根据https://stackoverflow.com/a/36408645/374638,也许这应该在&lt;env-variables&gt; 中。

【讨论】:

    猜你喜欢
    • 2020-09-10
    • 2016-10-12
    • 1970-01-01
    • 2012-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    相关资源
    最近更新 更多