从 GAE 将文件写入 Dropbox 帐户

发布于 2025-01-07 05:52:24 字数 1618 浏览 2 评论 0原文

我正在尝试从 GAE 应用程序在 Dropbox.com 文件夹中创建文件。 我已经完成了注册 Dropbox 应用程序的所有步骤,并在我的开发计算机上本地安装了来自 Dropbox 的 Python SDK。 (请参阅 dropbox.com API)。 当我在本地计算机上的 dropbox SDK 中使用 cli_client.py 测试脚本来访问 dropbox 时,一切都完美运行 - 可以“放置”文件等。

我现在想开始在 GAE 环境中工作,所以事情变得有点棘手。 一些帮助会很有用。

对于那些熟悉 Dropbox API 代码的人来说,到目前为止,我遇到了以下问题:

问题 1

rest.py Dropbox API 模块使用 pkg_resources 来获取安装在本地计算机安装的站点包中的证书。 我替换了

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

cert

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

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

问题 2

session.py Dropbox API 模块使用 oauth 模块,因此我将包含内容更改为 appengine 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

This isused when Calling

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

Authentication Error

但我仍然无法连接到 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')]

I am trying to create files in a Dropbox.com folder from a GAE application.
I have done all the steps the register a Dropbox application and installed the Python SDK from Dropbox locally on my development machine. (see dropbox.com API).
It all works perfectly when I use the cli_client.py test script in the dropbox SDK on my local machine to access dropbox - can 'put' files etc.

I now want to start working in GAE environment, so things get a bit tricky.
Some help would be useful.

For those familiar with the Dropbox API code, I had the following issues thus far:

Issue 1

The rest.py Dropbox API module uses pkg_resources to get the certs installed in site-packages of a local machine installation.
I replaced

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

with

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

and placed the cert file in my GAE application directory. Perhaps this is not quite right; see my authentication error code below.

Issue 2

The session.py Dropbox API module uses oauth module, so I changed the include to appengine oauth.

But raised an exception that GAE's oauth does not have OAuthConsumer method used by the Dropbox session.py module. So i downloaded oauth 1.0 and added to my application an now import this instead of GAE oauth.

Issue 3

GAE ssl module does not seem to have CERT_REQUIRED property.

This is a constant, so I changed

self.cert_reqs = ssl.CERT_REQUIRED

to

self.cert_reqs = 2

This is used when calling

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

Authentication Error

But I still can't connect to 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')]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

苄①跕圉湢 2025-01-14 05:52:24

这是我的 Dropbox Python SDK 1.4 修补版本,它非常适合与 Python 2.7 GAE 配合使用:dropbox_python_sdk_gae_patched.7z.base64。不需要额外的第三方库,只需要GAE环境提供的库。

仅测试文件上传(put_file)。以下是设置步骤:

  1. 将存档解压到 GAE 应用程序的根文件夹(如果主应用程序位于根文件夹中)。您可以使用 Base64 编码器/解码器 解码 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 帐户授予应用程序访问权限时获得的,您可以通过 token_store.txt 文件中的 cli_client.py(来自 DB Python SDK)获取它们。
  3. 在代码中使用如下:

    导入保管箱
    # ...
    def DropboxUpload(路径, 数据):
        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(数据)
        返回 cli.put_file(路径, data_file)
    # ...
    导入 json
    类 DropboxUploadHandlerExample(webapp2.RequestHandler):
        def get(自身):
            url =“http://www.google.com/”
            结果 = urlfetch.fetch(url)
            self.response.headers['Content-Type'] = 'application/json'
            self.response.out.write(json.dumps(DropboxUpload('/fetch_result.dat', result.content)))
    

Here's my patched version of Dropbox Python SDK 1.4 which works well for me with Python 2.7 GAE: dropbox_python_sdk_gae_patched.7z.base64. No extra third-party libraries needed, only those provided by GAE environment.

Only file uploading (put_file) is tested. Here're setup steps:

  1. Unpack archive to the root folder of GAE application (if main app is in the root folder). You can decode BASE64 using Base64 Encoder/Decoder: base64.exe -d dropbox_python_sdk_gae_patched.7z.base64 dropbox_python_sdk_gae_patched.7z.
  2. Setup APP_KEY, APP_SECRET, ACCESS_TYPE, ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET. First three are configured at dropbox application creation time. Last two are obtained when granting application access to specific dropbox account, you can get them through cli_client.py (from DB Python SDK) from token_store.txt file.
  3. Use in the code like this:

    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)))
    
那小子欠揍 2025-01-14 05:52:24

我使用自己的修补版本成功从 Google Appengine 上传到 Dropbox
Dropbox SDK 的: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()

I successfully uploaded from Google Appengine to Dropbox with my own patched version
of the Dropbox SDK: https://github.com/cklein/dropbox-client-python

The usage of urllib2 was replaced by huTools.http: https://github.com/hudora/huTools/

This is the code that is called in a request handler:

    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()
甲如呢乙后呢 2025-01-14 05:52:24

截至 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)

As of April 2016, none of the other suggestions work. (Dropbox API version 2, Python SDK version 6.2).

If you only need a few of the SDK functions, I found it easiest to just use the HTTP API directly:

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)
︶葆Ⅱㄣ 2025-01-14 05:52:24

我已经修补了 Dropbox Python SDK 2.2 版以在 Google App Engine 上运行。请在此处找到相关代码:

https://github.com/duncanhawthorne/gae-dropbox-python< /a>rest.py

的相关代码补丁(从github复制)在这里:

 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)

I have patched the Dropbox Python SDK version 2.2 to work on Google App Engine. Please find the relevant code here:

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

The relevant code patch (copied from github) for rest.py is here:

 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文