我得到了错误 invalid_grant 我已经在谷歌上看到了,但是在与这个问题斗争了几天之后。错误被抛出:
File file = insert.execute();
我只想将文件从我在 appengine 中的 webapp 上传到谷歌驱动器。我正在使用服务帐户在 API 访问 (https://code.google.com/apis/console/) 中生成的私钥对 (.p12):
Service account
Use service accounts to call Google APIs on behalf of your application instead of an end-user. Learn more
Client ID:
xxx-xxxxxx.apps.googleusercontent.com
Email address:
xxx-xxxxxxxxxxx@developer.gserviceaccount.com
Public key fingerprints:
a108d8713103e09d0013655c9f80458f03e3a38a – Delete...
在 Google APIs -> 驱动 SDK (https://code.google.com/apis/console/?api=drive#project:347347146680:drive_sdk) 我放了这个ClientID:
Drive Integration
OAuth Client ID (Required)
Enter the Client ID for your application. You can configure a client ID on the "API Access" panel.
任何帮助将不胜感激!谢谢!
我的代码:
struts.xml:
<interceptor name="gaeFileUploadInterceptor" class="com.struts2.gae.interceptor.GaeFileUploadInterceptor" />
<interceptor-stack name="fileUploadStack">
<interceptor-ref name="gaeFileUploadInterceptor"></interceptor-ref>
<interceptor-ref name="basicStack"></interceptor-ref>
</interceptor-stack>
<action name="uploadInit">
<result>jsp/common/upload.jsp</result>
</action>
<action name="upload" method="upload" class="com.lm.action.common.Upload">
<result>jsp/common/upload.jsp</result>
<interceptor-ref name="fileUploadStack"/>
<result name="success" type="stream">
<param name="contentType">image/jpeg,image/gif,image/png</param>
<param name="inputName">photoStream</param>
<param name="contentDisposition">filename="photo.jpg"</param>
<param name="bufferSize">1024</param>
</result>
</action>
上传.java:
//File uploading (see struts.xml interceptors & struts2-gae-0.1.jar
private String photo;
private String photoContentType; //The content type of the file
private String photoFileName; //The uploaded file name
private InputStream photoStream;
[...]
public String upload() {
try {
if (photo!=null) {
GoogleDrive.insertLocalFile("title","description",null,photoContentType,photo);
}
} catch (Exception e ) {
log.debug(new String(), e);
}
return SUCCESS2;
}
GoogleDrive.java:
public static File insertLocalFile(String title, String description,
String parentId, String mimeType, String data) {
File body = new File();
body.setTitle(title);
body.setDescription(description);
body.setMimeType(mimeType);
Drive service = null;
try {
service = getDriveService();
Files files = service.files();
InputStreamContent isc = new InputStreamContent(mimeType);
isc.setData(data);
Insert insert = files.insert(body, isc); //mediaContent);
File file = insert.execute();
return file;
} catch (IOException e) {
log.error(new String(), e);
return null;
}
}
public static Drive getDriveService() {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential;
Drive service = null;
try {
credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
//.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountId(SERVICE_ACCOUNT_ID)
.setServiceAccountScopes(DriveScopes.DRIVE_FILE)
.setServiceAccountPrivateKeyFromP12File(new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
.setServiceAccountUser(SERVICE_ACCOUNT_EMAIL)
.build();
service = new Drive.Builder(httpTransport, jsonFactory, null)
.setHttpRequestInitializer(credential).build();
} catch (GeneralSecurityException e) {
log.error(new String(), e);
} catch (IOException e) {
log.error(new String(), e);
}
return service;
}
堆栈跟踪:
com.google.api.client.auth.oauth2.TokenResponseException: 400 OK
{
"error" : "invalid_grant"
}
at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:103)
at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:303)
at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:323)
at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:340)
at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:505)
at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:266)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:857)
at com.google.api.client.googleapis.media.MediaHttpUploader.executeUploadInitiation(MediaHttpUploader.java:337)
at com.google.api.client.googleapis.media.MediaHttpUploader.upload(MediaHttpUploader.java:252)
at com.google.api.services.drive.Drive$Files$Insert.executeUnparsed(Drive.java:309)
at com.google.api.services.drive.Drive$Files$Insert.execute(Drive.java:331)
at util.google.GoogleDrive.insertLocalFile(GoogleDrive.java:365)
at com.lm.action.common.Upload.upload(Upload.java:108)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:115)
at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:453)
at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:292)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:255)
at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:236)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:236)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:90)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.struts2.gae.interceptor.GaeFileUploadInterceptor.intercept(GaeFileUploadInterceptor.java:275)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:511)
at org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:432)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:123)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:61)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:94)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:383)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)