1

我得到了错误 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)
4

1 回答 1

0

您误用了服务帐户 ID。你应该使用:

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

setServiceAccountUser()仅当您想模拟真实用户时才应使用该方法。

于 2012-11-06T14:07:57.607 回答