使用 GoogleCloudEndpoints 访问 GoogleCloudStorage
Access GoogleCloudStorage using GoogleCloudEndpoints
我正在处理这个项目,我正在使用 Google-App-Engine 后端通过 Google-Cloud-Endpoints 连接到 Android 应用程序。对于 Google-Cloud-Datastore 访问,我正在使用 Objectify,一切正常。
现在我决定添加将图像上传到 Google-Cloud-Storage 的功能,但我找不到关于如何使用 Google-Cloud-Endpoints 执行此操作的明确解释设置。
我找到了如何将 Google-Cloud-Storage 与 Google-App-Engine 一起使用的以下说明:
https://cloud.google.com/appengine/docs/java/googlecloudstorageclient/app-engine-cloud-storage-sample
但文章没有将其添加到端点 Api,而是编写了一个额外的 servlet。
此外,我发现 Android 的 upload/download 示例:
github.com /thorrism/GoogleCloudExample
遗憾的是,这是使用 Google 云存储 API 直接访问 Google-云存储,您需要将 P12 文件添加到资产文件夹,这似乎不安全。
我的 Google-App-Engine 代码如下所示:
@Api(
name = "example",
version = "v1",
scopes = { Constants.EMAIL_SCOPE },
clientIds = { Constants.WEB_CLIENT_ID, Constants.ANDROID_CLIENT_ID, Constants.API_EXPLORER_CLIENT_ID },
audiences = {Constants.ANDROID_AUDIENCE},
description = "API for the Example Backend application."
)
public class ExampleApi{
@ApiMethod(name = "doSomething", path = "dosomething", httpMethod = HttpMethod.POST)
public String doSomething(@Named("text") String text){
TestEntity test = new TestEntity(text);
ofy().save().entity(test).now();
return test;
}
上传后,我生成了端点客户端库并将其导入到我的 android 项目中。
然后我从 Android 调用端点,就像这里解释的那样:
public static com.appspot.******.example.Example buildServiceHandler(Context context, String email) {
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(
context, AppConstants.AUDIENCE);
credential.setSelectedAccountName(email);
com.appspot.******.example.Example.Builder builder = new com.appspot.******.example.Example.Builder(
AppConstants.HTTP_TRANSPORT,
AppConstants.JSON_FACTORY, null);
builder.setApplicationName("example-server");
return builder.build();
}
sApiServiceHandler = buildServiceHandlerWithAuth(context,email);
每个Api-我这样调用的方法:
com.appspot.******.example.Example.DoSomething doSomething = sApiServiceHandler.doSomething(someString);
doSomething.execute();
所有这些工作正常,但仅适用于 storing/receiving 数据存储实体。我如何使用 Google Cloud Endpoints 设置将 uploading/downloading 文件传输到 Google Cloud Storage?
是否可以使用已经构建的 ServiceHandler 通过 Endpoints 将带有我的图像数据的 POST 发送到 UploadServlet ?
是否可以从端点方法调用 servlet?我应该如何将 Post 发送到 Servlet,我将如何进行身份验证?
如有任何帮助或建议,我们将不胜感激!
有多种方法可以做到这一点,但最推荐的方法是使用 Signed URLs,这样您的 Android 应用程序就可以将文件安全地直接上传到 Google 云存储,无需通过您的 Endpoints 后端。基本流程是:
1) 创建一个 Endpoints 方法,将 creates a new signed URL 和 returns 发送到 Android 客户端。在服务器上签署 URL 仍然需要 P12 密钥,但存储在 App Engine 上,而不是在客户端上,因此是安全的。尝试为 URL 使用较短的到期时间,例如不超过 5 分钟。
2) Android 客户端 upload the file directly to the signed URL, as you would doing a normal HTTP PUT to the Cloud Storage XML API to upload a file (resumable uploads with the JSON API 也受支持,但不在此处介绍)。
您的端点方法可能如下所示:
@ApiMethod(name = "getUploadUrl", path = "getuploadurl", httpMethod = HttpMethod.GET)
public MyApiResponse getUploadUrl(@Named("fileName") String fileName
@Named("contentType" String contentType)
{
String stringToSign
= "PUT\n" + contentType
+ "\n" + EXPIRATION_TIMESTAMP_EPOCH_SECONDS + "\n"
+ YOUR_GCS_BUCKET + "/" + fileName;
// Load P12 key
FileInputStream fileInputStream = new FileInputStream(PATH_TO_P12_KEY);
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(fileInputStream, password);
PrivateKey key = keyStore.getKey(privatekey", YOUR_P12_KEY_PASSWORD);
// Get signature
Signature signer = Signature.getInstance("SHA256withRSA");
signer.initSign(key);
signer.update(stringToSign.getBytes("UTF-8"));
byte[] rawSignature = signer.sign();
String signature = new String(Base64.encodeBase64(rawSignature, false), "UTF-8");
// Construct signed url
String url
= "http://storage.googleapis.com/" + YOUR_GCS_BUCKET + fileName
+ "?GoogleAccessId=" + P12_KEY_SERVICE_ACCOUNT_CLIENT_ID
+ "&Expires=" + EXPIRATION_TIMESTAMP_EPOCH_SECONDS
+ "&Signature=" + URLEncoder.encode(signature, "UTF-8");
// Endpoints doesn't let you return 'String' directly
MyApiResponse response = new MyApiResponse();
response.setString(url);
return response;
}
在Android这边,你可以使用这样的方法:
// Get the upload URL from the API
getUploadUrl = sApiServiceHandler.getUploadUrl(fileName, contentType);
MyApiResponse response = getUploadUrl.execute();
String uploadUrl = response.getString();
// Open connection to GCS
URL url = new URL(uploadUrl);
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setDoOutput(true);
httpConnection.setRequestMethod("PUT");
httpConnection.setRequestProperty("Content-Type", contentType);
// Write file data
OutputStreamWriter out = new OutputStreamWriter(httpConnection.getOutputStream());
out.write(fileData);
out.flush();
// Get response, check status code etc.
InputStreamReader in = new InputStreamReader(httpConnection.getInputStream());
// ...
(免责声明:我只是在文本编辑器中随意输入代码,并没有实际测试它,但它应该足以让您大致了解。)
我正在处理这个项目,我正在使用 Google-App-Engine 后端通过 Google-Cloud-Endpoints 连接到 Android 应用程序。对于 Google-Cloud-Datastore 访问,我正在使用 Objectify,一切正常。
现在我决定添加将图像上传到 Google-Cloud-Storage 的功能,但我找不到关于如何使用 Google-Cloud-Endpoints 执行此操作的明确解释设置。
我找到了如何将 Google-Cloud-Storage 与 Google-App-Engine 一起使用的以下说明: https://cloud.google.com/appengine/docs/java/googlecloudstorageclient/app-engine-cloud-storage-sample
但文章没有将其添加到端点 Api,而是编写了一个额外的 servlet。
此外,我发现 Android 的 upload/download 示例:
github.com /thorrism/GoogleCloudExample
遗憾的是,这是使用 Google 云存储 API 直接访问 Google-云存储,您需要将 P12 文件添加到资产文件夹,这似乎不安全。
我的 Google-App-Engine 代码如下所示:
@Api(
name = "example",
version = "v1",
scopes = { Constants.EMAIL_SCOPE },
clientIds = { Constants.WEB_CLIENT_ID, Constants.ANDROID_CLIENT_ID, Constants.API_EXPLORER_CLIENT_ID },
audiences = {Constants.ANDROID_AUDIENCE},
description = "API for the Example Backend application."
)
public class ExampleApi{
@ApiMethod(name = "doSomething", path = "dosomething", httpMethod = HttpMethod.POST)
public String doSomething(@Named("text") String text){
TestEntity test = new TestEntity(text);
ofy().save().entity(test).now();
return test;
}
上传后,我生成了端点客户端库并将其导入到我的 android 项目中。
然后我从 Android 调用端点,就像这里解释的那样:
public static com.appspot.******.example.Example buildServiceHandler(Context context, String email) {
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(
context, AppConstants.AUDIENCE);
credential.setSelectedAccountName(email);
com.appspot.******.example.Example.Builder builder = new com.appspot.******.example.Example.Builder(
AppConstants.HTTP_TRANSPORT,
AppConstants.JSON_FACTORY, null);
builder.setApplicationName("example-server");
return builder.build();
}
sApiServiceHandler = buildServiceHandlerWithAuth(context,email);
每个Api-我这样调用的方法:
com.appspot.******.example.Example.DoSomething doSomething = sApiServiceHandler.doSomething(someString);
doSomething.execute();
所有这些工作正常,但仅适用于 storing/receiving 数据存储实体。我如何使用 Google Cloud Endpoints 设置将 uploading/downloading 文件传输到 Google Cloud Storage? 是否可以使用已经构建的 ServiceHandler 通过 Endpoints 将带有我的图像数据的 POST 发送到 UploadServlet ? 是否可以从端点方法调用 servlet?我应该如何将 Post 发送到 Servlet,我将如何进行身份验证?
如有任何帮助或建议,我们将不胜感激!
有多种方法可以做到这一点,但最推荐的方法是使用 Signed URLs,这样您的 Android 应用程序就可以将文件安全地直接上传到 Google 云存储,无需通过您的 Endpoints 后端。基本流程是:
1) 创建一个 Endpoints 方法,将 creates a new signed URL 和 returns 发送到 Android 客户端。在服务器上签署 URL 仍然需要 P12 密钥,但存储在 App Engine 上,而不是在客户端上,因此是安全的。尝试为 URL 使用较短的到期时间,例如不超过 5 分钟。
2) Android 客户端 upload the file directly to the signed URL, as you would doing a normal HTTP PUT to the Cloud Storage XML API to upload a file (resumable uploads with the JSON API 也受支持,但不在此处介绍)。
您的端点方法可能如下所示:
@ApiMethod(name = "getUploadUrl", path = "getuploadurl", httpMethod = HttpMethod.GET)
public MyApiResponse getUploadUrl(@Named("fileName") String fileName
@Named("contentType" String contentType)
{
String stringToSign
= "PUT\n" + contentType
+ "\n" + EXPIRATION_TIMESTAMP_EPOCH_SECONDS + "\n"
+ YOUR_GCS_BUCKET + "/" + fileName;
// Load P12 key
FileInputStream fileInputStream = new FileInputStream(PATH_TO_P12_KEY);
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(fileInputStream, password);
PrivateKey key = keyStore.getKey(privatekey", YOUR_P12_KEY_PASSWORD);
// Get signature
Signature signer = Signature.getInstance("SHA256withRSA");
signer.initSign(key);
signer.update(stringToSign.getBytes("UTF-8"));
byte[] rawSignature = signer.sign();
String signature = new String(Base64.encodeBase64(rawSignature, false), "UTF-8");
// Construct signed url
String url
= "http://storage.googleapis.com/" + YOUR_GCS_BUCKET + fileName
+ "?GoogleAccessId=" + P12_KEY_SERVICE_ACCOUNT_CLIENT_ID
+ "&Expires=" + EXPIRATION_TIMESTAMP_EPOCH_SECONDS
+ "&Signature=" + URLEncoder.encode(signature, "UTF-8");
// Endpoints doesn't let you return 'String' directly
MyApiResponse response = new MyApiResponse();
response.setString(url);
return response;
}
在Android这边,你可以使用这样的方法:
// Get the upload URL from the API
getUploadUrl = sApiServiceHandler.getUploadUrl(fileName, contentType);
MyApiResponse response = getUploadUrl.execute();
String uploadUrl = response.getString();
// Open connection to GCS
URL url = new URL(uploadUrl);
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setDoOutput(true);
httpConnection.setRequestMethod("PUT");
httpConnection.setRequestProperty("Content-Type", contentType);
// Write file data
OutputStreamWriter out = new OutputStreamWriter(httpConnection.getOutputStream());
out.write(fileData);
out.flush();
// Get response, check status code etc.
InputStreamReader in = new InputStreamReader(httpConnection.getInputStream());
// ...
(免责声明:我只是在文本编辑器中随意输入代码,并没有实际测试它,但它应该足以让您大致了解。)