【发布时间】:2015-04-13 03:15:42
【问题描述】:
我想使用 GCS 存储桶作为我的 blobstore 的支持,但我不知道如何在我的开发服务器上设置一个。
有使用实时服务器上的开发人员控制台执行此操作的说明,但我找不到有关如何在本地开发计算机上执行此操作的任何信息...
【问题讨论】:
标签: java google-app-engine google-cloud-storage
我想使用 GCS 存储桶作为我的 blobstore 的支持,但我不知道如何在我的开发服务器上设置一个。
有使用实时服务器上的开发人员控制台执行此操作的说明,但我找不到有关如何在本地开发计算机上执行此操作的任何信息...
【问题讨论】:
标签: java google-app-engine google-cloud-storage
对于那些试图让 Google Cloud Storage 完全从他们的本地 Java 开发应用服务器工作的人来说,我认为再提供一个答案会有所帮助。我设法让我的本地开发应用服务器与非本地 Google Cloud Storage 一起工作,但只是在挖掘代码并弄清楚需要什么 - 似乎没有这方面的文档。
目标是让这段代码在本地工作,它从 GCS 读取文件:
GcsService gcsService =
GcsServiceFactory.createGcsService(RetryParams.getDefaultInstance());
int fileSize = (int) gcsService.getMetadata(gcsFilename).getLength();
ByteBuffer byteBuffer = ByteBuffer.allocate(fileSize);
GcsInputChannel inputChannel = gcsService.openReadChannel(gcsFilename, 0);
int readResult = inputChannel.read(byteBuffer);
byte[] fileBytes = byteBuffer.array();
如果您尝试在本地执行此操作,您将找不到任何已上传到 GCS 的文件,因为它会尝试使用假的本地 GCS。不幸的是,我还没有找到上传到这个本地 GCS 的好方法,所以这不是很有用(没有云版本中的文件资源管理器,并且 gsutil 不适用于它)。因此,我们将让它在本地开发应用服务器中运行时与非本地(云)GCS 一起工作。
为此,请注意 GcsService 是由以下代码块在 com.google.appengine.tools.cloudstorage.GcsServiceFactory 中创建的:
if (location == SystemProperty.Environment.Value.Production || hasCustomAccessTokenProvider()) {
rawGcsService = OauthRawGcsServiceFactory.createOauthRawGcsService(builder.build());
} else if (location == SystemProperty.Environment.Value.Development) {
rawGcsService = LocalRawGcsServiceFactory.createLocalRawGcsService();
上面说你需要指定一个自定义访问令牌提供者来获取非本地服务,你可以通过定义一个系统属性来做到这一点。对于应用引擎应用,您可以像这样在 appengine-web.xml 中执行此操作:
<system-properties>
<property name="gcs_access_token_provider" value="com.mypackage.MyAccessTokenProvider" />
</system-properties>
该属性的此值是您定义的实现 com.google.appengine.tools.cloudstorage.oauth.AccessTokenProvider 的类,它为您的应用程序提供访问令牌。该类需要创建一个可用于获取访问令牌的 GoogleCredential,使用 https://developers.google.com/identity/protocols/OAuth2ServiceAccount#authorizingrequests 上的 GoogleCredential 的“其他”说明。
现在它将创建一个与云对话的 OAuth GcsService,并且您不需要使用虚假的本地存储。
【讨论】:
事实证明,您根本不需要执行任何设置。我只是假设在使用 blobstore 上传时有一个具有特定名称的文件,并且是自动为我创建的。
顺便说一句,似乎没有任何地方记录您如何浏览开发服务器存储中的文件。您可以通过在 Datastore Viewer 管理员访问本地开发服务器的权限中选择 __GsFileInfo__ 实体来完成此操作。
【讨论】:
您需要为 App Engine 下载并集成 Google Cloud Storage Client Library。
该库为您提供GcsService,它类似于BlobstoreService,因此您可以写入文件、读取文件、删除文件以及云存储提供的其他功能
当您在开发环境中使用代码时,上传的文件存储在appengine-generated 文件夹中,并在本地数据存储中创建一个__GsFileInfo__ 实体,该实体保留附加到文件的元数据
这个库也可以在线使用,因此您的代码可以同时用于开发和生产环境。
在这里您可以找到Getting Started 指南和完整的JavaDoc 参考
【讨论】:
认为这可以使用最近的一些发现。对我来说,本地云存储根本不起作用。它失败并显示 GsFileInfo 是受保护实体的错误。如果您不启动本地数据存储模拟器(这意味着它使用远程云存储),它可以正常工作。
这似乎与谷歌的最新文档相吻合:https://cloud.google.com/appengine/docs/standard/java/using-cloud-storage#using_cloud_storage_with_the_local_development_server
App Engine 本地开发服务器不模拟 Cloud Storage, 因此所有 Cloud Storage 请求都必须通过 Internet 发送到 实际的 Cloud Storage 存储分区。
因此,@learnj12 的答案是最好的方法。但是 GoogleCredential 已被弃用,目前尚不清楚如何实现 com.google.appengine.tools.cloudstorage.oauth.AccessTokenProvider。
这对我有用:
import com.google.appengine.api.appidentity.AppIdentityService;
import com.google.appengine.api.appidentity.AppIdentityServiceFactory;
import com.google.appengine.tools.cloudstorage.oauth.AccessTokenProvider;
public class GCSTokenProvider implements AccessTokenProvider {
@Override
public AppIdentityService.GetAccessTokenResult getNewAccessToken(List<String> list) {
return AppIdentityServiceFactory.getAppIdentityService().getAccessToken(Collections.singleton("cloud-platform"));
}
}
注意。我正在使用服务帐户,并使用gcloud 登录。
【讨论】: