【发布时间】:2014-11-23 23:43:55
【问题描述】:
我正在尝试按照 sample from google 和 GcsExampleServlet.java 来设置 Google Cloud Storage 文件上传。我已经完成了所有步骤,但是当我将项目部署到 aggengine 并尝试在 GCS 中上传简单文本时,它会失败并显示以下日志:
com.google.appengine.tools.cloudstorage.NonRetriableException: com.google.appengine.tools.cloudstorage.NonRetriableException: com.google.appengine.api.appidentity.AppIdentityServiceFailureException:
The AppIdentity service threw an unexpected error. Details:
at com.google.appengine.tools.cloudstorage.RetryHelper.doRetry(RetryHelper.java:120)
at com.google.appengine.tools.cloudstorage.RetryHelper.runWithRetries(RetryHelper.java:166)
at com.google.appengine.tools.cloudstorage.RetryHelper.runWithRetries(RetryHelper.java:156)
at com.google.appengine.tools.cloudstorage.GcsServiceImpl.createOrReplace(GcsServiceImpl.java:70)
at com.appart.storage.server.GcsExampleServlet.doPost(GcsExampleServlet.java:88)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
(...)
不过,代码中并没有什么复杂的地方……在 web.xml 中,我已经配置了 servlet:
<servlet>
<servlet-name>GcsExample</servlet-name>
<servlet-class>
com.example.server.GcsExampleServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GcsExample</servlet-name>
<url-pattern>/gcs/*</url-pattern>
</servlet-mapping>
这里是 servlet GcsExampleServlet.java(与谷歌示例完全相同):
@SuppressWarnings("serial")
public class GcsExampleServlet extends HttpServlet {
private final GcsService gcsService = GcsServiceFactory.createGcsService(new RetryParams.Builder()
.initialRetryDelayMillis(10)
.retryMaxAttempts(10)
.totalRetryPeriodMillis(15000)
.build());
//...
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException
{
GcsOutputChannel outputChannel =
gcsService.createOrReplace(getFileName(req), GcsFileOptions.getDefaultInstance());
copy(req.getInputStream(), Channels.newOutputStream(outputChannel));
}
private void copy(InputStream input, OutputStream output) throws IOException {
try {
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = input.read(buffer);
while (bytesRead != -1) {
output.write(buffer, 0, bytesRead);
bytesRead = input.read(buffer);
}
} finally {
input.close();
output.close();
}
}
}
这是我的 upload.html 文件:
<form action="/upload.html" enctype="text/plain" method="get" name="putFile" id="putFile">
<div>
Bucket: <input type="text" name="bucket" />
File Name: <input type="text" name="fileName" />
<br /> File Contents: <br />
<textarea name="content" id="content" rows="3" cols="60"></textarea>
<br />
<input type="submit" onclick='uploadFile(this)' value="Upload Content" />
</div>
</form>
<script>
function uploadFile() {
var bucket = document.forms["putFile"]["bucket"].value;
var filename = document.forms["putFile"]["fileName"].value;
if (bucket == null || bucket == "" || filename == null || filename == "") {
alert("Both Bucket and FileName are required");
return false;
} else {
var postData = document.forms["putFile"]["content"].value;
document.getElementById("content").value = null;
var request = new XMLHttpRequest();
request.open("POST", "/gcs/" + bucket + "/" + filename, false);
request.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
request.send(postData);
}
}
</script>
我已启用计费,创建了一个存储桶,但 AppIdentity 错误仍然出现。我没有 Oauth,启用了云存储 API,用于上传的 appengine 帐户对存储桶具有写入权限。我什至尝试了一个
gsutil acl ch -u warm-particle-718@appspot.gserviceaccount.com:WRITE gs://ctrlxbucket
确保用户对我的存储桶具有写入权限。
请帮我弄清楚这个错误是什么意思,我从几天就一直呆在这里:(
非常感谢
PS:如果您只有一些 GCS 的工作示例(不是 google 的),我也会很高兴,因为围绕该主题的内容不多。
【问题讨论】:
-
我最近创建的任何与 GCS 对话的 AppEngine 项目都有类似的问题。在 python AppEngine 代码中,我得到了与获取 GCS 访问的令牌代码相关的 InternalError。问题似乎是在任何新的 AppEngine 应用程序中都缺少凭据,例如如果您在开发控制台中查看 Api & auth -> Credentials,它可能没有服务帐户的“Compute Engine 和 AppEngine”客户端 ID。我有一个去年创建的旧版应用程序,但运行良好。
-
@Abhijit Kalamkar +1。我也一样。我的旧项目运行良好。但是 2 天前我用相同的代码创建了新项目,并且发生了这个错误。我还注意到 Compute Engine 凭据在新项目中消失了,但我想这不是因为 CtrlX 在此comment 中提到了 593689673236-compute@developer.gserviceaccount.com 帐户。我想解决方案是在一些 AppEngine 配置中。
-
@Juniper 解决了这个问题,在cloud.google.com/appengine/docs/python/googlecloudstorageclient/… 上看到了这个注释 注意:在一些不寻常的情况下,您可能无法使用“添加成员”表单添加您的服务帐户。如果发生这种情况,您必须将应用的服务帐号添加到存储桶 ACL。有关更多信息,请参阅授予您的存储桶或对象的权限。
-
@AbhijitKalamkar 听起来很有趣!我正在尝试您的解决方案,但是在文档中,当 gsutil 检索存储桶 ACL 时,它似乎是一个 xml。但我检索了一个 JSON。你有相同的 JSON ACL 文件吗?
-
@AbhijitKalamkar 实际上,它有效(使用 JSON 而不是文档中所说的 XML)!我必须添加 { "email": "warm-particle-718@appspot.gserviceaccount.com", "entity": "user-warm-particle-718@appspot.gserviceaccount.com", "role": "WRITER" } 到 myACL.txt 和 myDefAcl.txt 您能否创建一个答案而不是评论,以便我接受它? (尝试提供文档中提供的用于生成 ACL 的集合)再次感谢
标签: java google-app-engine google-cloud-storage