2012-02-19 41 views
15

我正尝试在GAE应用程序的Dropbox.com文件夹中创建文件。 我已经完成了注册Dropbox应用程序的所有步骤,并在我的开发机器上从Dropbox本地安装了Python SDK。 (请参阅dropbox.com API)。 当我在本地机器的Dropbox SDK中使用cli_client.py测试脚本访问dropbox - 可以“放置”文件等时,它完全正常工作。将文件写入GAE的Dropbox帐户

我现在想要开始在GAE环境中工作,有点棘手。 一些帮助将是有用的。

对于那些熟悉的Dropbox API代码,我有以下问题迄今:

1期

的rest.py的Dropbox API模块使用pkg_resources才能得到安装在定点的证书本地机器安装的软件包。 我换成

TRUSTED_CERT_FILE = pkg_resources.resource_filename(__name__, 'trusted-certs.crt') 

TRUSTED_CERT_FILE = file('trusted-certs.crt') 

并放置在证书文件在我的GAE应用程序目录。也许这是不正确的;请参阅下面我的验证错误代码。

问题2

session.py收存箱API模块使用的OAuth模块,所以改变了包括到应用服务引擎的OAuth。

但提出了一个例外,GAE的oauth没有Dropbox session.py模块使用的OAuthConsumer方法。所以我下载了oauth 1.0,并添加到我的应用程序中,而不是GAE oauth。

3期

GAE SSL模块似乎并不具有CERT_REQUIRED财产。

这是一个常数,所以我改变

self.cert_reqs = ssl.CERT_REQUIRED 

self.cert_reqs = 2 

这是调用

ssl.wrap_socket(sock, cert_reqs=self.cert_reqs, ca_certs=self.ca_certs) 

验证错误

时使用

但我仍然无法连接到Dropbox的:

Status: 401 
Reason: Unauthorized 
Body: {"error": "Authentication failed"} 
Headers: [('date', 'Sun, 19 Feb 2012 15:11:12 GMT'), ('transfer-encoding', 'chunked'), ('connection', 'keep-alive'), ('content-type', 'application/json'), ('server', 'dbws')] 
+0

我希望有人回答了这个。同时,虽然我不确定pkg_resources.resource_filename()是什么,但我认为它返回一个文件名,而不是打开的文件,而file()打开指定的文件并返回一个流(打开文件)对象。您可能想尝试使用TRUSTED_CERT_FILE ='trusted-certs.crt''。 – 2012-02-20 05:03:57

+0

感谢Guido - 会尝试 – erickCo 2012-02-20 13:39:04

+0

Guido,你说的没错,'pkg_resources.resource_filename()'返回的类型是'str'。该值是证书文件的完整路径。所以我按照你的建议做了改变。唉,仍然是同样的错误。 – erickCo 2012-02-20 13:54:20

回答

7

这里是我的补丁的Dropbox的Python SDK 1.4与Python 2.7版GAE对我的作品很好的版本:dropbox_python_sdk_gae_patched.7z.base64。不需要额外的第三方库,只有GAE环境提供的库。

仅测试文件上传(put_file)。这里的设置步骤如下:

  1. 将归档解压到GAE应用程序的根文件夹(如果主应用程序位于根文件夹中)。您可以使用Base64 Encoder/Decoder解码BASE64:base64.exe -d dropbox_python_sdk_gae_patched.7z.base64 dropbox_python_sdk_gae_patched.7z
  2. 设置APP_KEY,APP_SECRET,ACCESS_TYPE,ACCESS_TOKEN_KEY,ACCESS_TOKEN_SECRET。前三个是在Dropbox应用程序创建时配置的。当授予应用程序对特定Dropbox帐户的访问权时,可以获得最后两个帐户,您可以通过cli_client.py(来自DB Python SDK)从token_store.txt文件获取它们。
  3. 使用在这样的代码:

    import dropbox 
    # ... 
    def DropboxUpload(path, data): 
        sess = dropbox.session.DropboxSession(APP_KEY, APP_SECRET, ACCESS_TYPE) 
        sess.set_token(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET) 
        cli = dropbox.client.DropboxClient(sess) 
        data_file = StringIO.StringIO(data) 
        return cli.put_file(path, data_file) 
    # ... 
    import json 
    class DropboxUploadHandlerExample(webapp2.RequestHandler): 
        def get(self): 
         url = "http://www.google.com/" 
         result = urlfetch.fetch(url) 
         self.response.headers['Content-Type'] = 'application/json' 
         self.response.out.write(json.dumps(DropboxUpload('/fetch_result.dat', result.content))) 
    
+1

以下您可以更新到最新的Dropbox sdk,DropboxOAuth2FlowNoRedirect吗? – 2014-08-20 12:36:05

3

我从谷歌AppEngine上成功上传我自己的补丁 Dropbox的SDK的版本的Dropbox:https://github.com/cklein/dropbox-client-python

的urllib2的使用被取代huTools。HTTP:https://github.com/hudora/huTools/

这是被称为在请求处理程序的代码:

db_client = dropbox.get_dropbox_client(consumer_key='', consumer_secret='', access_token_key='', access_token_secret='') 
    fileobj = StringIO.StringIO(data) 
    path = '/some/path/filename' 
    resp = db_client.put_file(path, fileobj) 
    fileobj.close() 
1

我已经修补了Dropbox的的Python SDK 2.2版对谷歌App Engine的工作。请在这里找到相关代码:

https://github.com/duncanhawthorne/gae-dropbox-python

相关的代码打补丁(从GitHub复制)为rest.py是在这里:

import io 
import pkg_resources 
-import socket 
+#import socket 
import ssl 
import sys 
import urllib 
+import urllib2 

+def mock_urlopen(method,url,body,headers,preload_content): 
+ request = urllib2.Request(url, body, headers=headers) 
+ r = urllib2.urlopen(request) 
+ return r   
+  
try: 
    import json 
except ImportError: 
@@ -23,7 +29,10 @@ 

SDK_VERSION = "2.2.0" 

-TRUSTED_CERT_FILE = pkg_resources.resource_filename(__name__, 'trusted-certs.crt') 
+try: 
+ TRUSTED_CERT_FILE = pkg_resources.resource_filename(__name__, 'trusted-certs.crt') 
+except: 
+ TRUSTED_CERT_FILE = file('trusted-certs.crt') 


class RESTResponse(io.IOBase): 
@@ -125,6 +134,7 @@ def flush(self): 
     pass 

def create_connection(address): 
+ return 
    host, port = address 
    err = None 
    for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM): 
@@ -152,7 +162,7 @@ def json_loadb(data): 


class RESTClientObject(object): 
- def __init__(self, max_reusable_connections=8, mock_urlopen=None): 
+ def __init__(self, max_reusable_connections=8, mock_urlopen=mock_urlopen): 
     """ 
     Parameters 
      max_reusable_connections 
@@ -206,7 +216,7 @@ def request(self, method, url, post_params=None, body=None, headers=None, raw_re 
       raise ValueError("headers should not contain newlines (%s: %s)" % 
            (key, value)) 

-  try: 
+  if True: 
      # Grab a connection from the pool to make the request. 
      # We return it to the pool when caller close() the response 
      urlopen = self.mock_urlopen if self.mock_urlopen else self.pool_manager.urlopen 
@@ -217,14 +227,14 @@ def request(self, method, url, post_params=None, body=None, headers=None, raw_re 
       headers=headers, 
       preload_content=False 
      ) 
-   r = RESTResponse(r) # wrap up the urllib3 response before proceeding 
-  except socket.error as e: 
-   raise RESTSocketError(url, e) 
-  except urllib3.exceptions.SSLError as e: 
-   raise RESTSocketError(url, "SSL certificate error: %s" % e) 
+   #r = RESTResponse(r) # wrap up the urllib3 response before proceeding 
+  #except socket.error as e: 
+  # raise RESTSocketError(url, e) 
+  #except urllib3.exceptions.SSLError as e: 
+  # raise RESTSocketError(url, "SSL certificate error: %s" % e) 

-  if r.status not in (200, 206): 
-   raise ErrorResponse(r, r.read()) 
+  #if r.status not in (200, 206): 
+  # raise ErrorResponse(r, r.read()) 

     return self.process_response(r, raw_response) 

@@ -321,10 +331,11 @@ def PUT(cls, *n, **kw): 
     return cls.IMPL.PUT(*n, **kw) 


-class RESTSocketError(socket.error): 
+class RESTSocketError(): 
    """A light wrapper for ``socket.error`` that adds some more information.""" 

    def __init__(self, host, e): 
+  return 
     msg = "Error connecting to \"%s\": %s" % (host, str(e)) 
     socket.error.__init__(self, msg) 
2

随着2016年4月的,没有其他工作的建议。 (Dropbox API版本2,Python SDK版本6.2)。

如果您只需要几个的SDK功能,我发现它最简单的只使用直接HTTP API:

def files_upload(f, path, mode='add', autorename=False, mute=False): 

    args = { 
     'path': path, 
     'mode': mode, 
     'autorename': autorename, 
     'mute': mute, 
    } 

    headers = { 
     'Authorization': 'Bearer {}'.format(ACCESS_TOKEN), 
     'Dropbox-API-Arg': json.dumps(args), 
     'Content-Type': 'application/octet-stream', 
    } 

    request = urllib2.Request('https://content.dropboxapi.com/2/files/upload', f, headers=headers) 
    r = urllib2.urlopen(request)