2012-02-19 4 views
15

Tôi đang cố gắng tạo tệp trong thư mục Dropbox.com từ ứng dụng GAE. Tôi đã thực hiện tất cả các bước đăng ký một ứng dụng Dropbox và cài đặt Python SDK từ Dropbox cục bộ trên máy phát triển của tôi. (xem API dropbox.com). Tất cả hoạt động hoàn hảo khi tôi sử dụng kịch bản lệnh kiểm tra cli_client.py trong dropbox SDK trên máy cục bộ của tôi để truy cập dropbox - có thể 'đặt' các tệp, v.v.Ghi tệp vào tài khoản Dropbox từ GAE

Bây giờ tôi muốn bắt đầu làm việc trong môi trường GAE một chút khó khăn. Một số trợ giúp sẽ hữu ích.

Đối với những người quen thuộc với mã Dropbox API, tôi đã có những vấn đề sau vậy, đến nay:

Issue 1

Các rest.py Dropbox mô-đun API sử dụng pkg_resources để có được các Certs cài đặt trong trang web- các gói cài đặt máy cục bộ. tôi thay

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

với

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

và đặt file cert trong thư mục ứng dụng GAE tôi. Có lẽ điều này không đúng; xem mã lỗi xác thực của tôi bên dưới.

Issue 2

Các session.py Dropbox mô-đun API sử dụng oauth mô-đun, vì vậy tôi đã thay đổi bao gồm để AppEngine oauth.

Nhưng đã nêu một ngoại lệ là oauth của GAE không có phương thức OAuthConsumer được mô-đun session.py của Dropbox sử dụng. Vì vậy, tôi đã tải xuống oauth 1.0 và được thêm vào ứng dụng của tôi, bây giờ, hãy nhập mã này thay vì GAE oauth.

Issue 3

GAE mô-đun ssl dường như không có tài sản CERT_REQUIRED.

Đây là một hằng số, vì vậy tôi đã thay đổi

self.cert_reqs = ssl.CERT_REQUIRED 

để

self.cert_reqs = 2 

này được sử dụng khi gọi

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

Xác thực Lỗi

Nhưng tôi vẫn không thể kết nối với 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

Tôi hy vọng ai đó trả lời này. Trong thời gian đó, trong khi tôi không chắc pkg_resources.resource_filename() là gì, tôi nghĩ nó trả về một tên tệp, không phải là một tệp mở, trong khi tệp() mở tệp có tên và trả về một đối tượng dòng (tệp mở). Thay vào đó, bạn có thể muốn thử 'TRUSTED_CERT_FILE = 'trust-certs.crt''. –

+0

Cảm ơn Guido - sẽ thử rằng – erickCo

+0

Guido, bạn đúng, kiểu được trả về bởi 'pkg_resources.resource_filename()' là 'str'. Giá trị là đường dẫn đầy đủ đến tệp certs. Vì vậy, tôi đã thực hiện thay đổi khi bạn đề xuất. Than ôi, vẫn còn lỗi tương tự. – erickCo

Trả lời

7

Dưới đây là phiên bản vá của tôi về Dropbox Python SDK 1.4 mà hoạt động tốt cho tôi với Python 2.7 GAE: dropbox_python_sdk_gae_patched.7z.base64. Không cần thêm thư viện của bên thứ ba, chỉ những thư viện được cung cấp bởi môi trường GAE.

Chỉ tải lên tệp (put_file) mới được kiểm tra. Dưới đây là các bước thiết lập:

  1. Mở gói lưu trữ vào thư mục gốc của ứng dụng GAE (nếu ứng dụng chính nằm trong thư mục gốc). Bạn có thể giải mã BASE64 bằng cách sử dụng Base64 Encoder/Decoder: base64.exe -d dropbox_python_sdk_gae_patched.7z.base64 dropbox_python_sdk_gae_patched.7z.
  2. Thiết lập APP_KEY, APP_SECRET, ACCESS_TYPE, ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET. Đầu tiên ba được cấu hình tại thời gian tạo ứng dụng dropbox. Cuối cùng hai được lấy khi cấp quyền truy cập ứng dụng vào tài khoản dropbox cụ thể, bạn có thể lấy chúng thông qua cli_client.py (từ DB Python SDK) từ tệp token_store.txt.
  3. Sử dụng trong các mã như thế này:

    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

Bạn có thể cập nhật điều này lên sdk dropbox mới nhất, một trong đó có DropboxOAuth2FlowNoRedirect không? –

3

Tôi đã tải lên thành công từ Google AppEngine Dropbox với phiên bản của riêng tôi vá của Dropbox SDK: https://github.com/cklein/dropbox-client-python

Việc sử dụng urllib2 được thay thế bằng huTools.http: https://github.com/hudora/huTools/

Đây là mã đó được gọi là trong một handler yêu cầu:

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

Tôi đã vá phiên bản Dropbox Python SDK 2.2 để làm việc trên Google App Engine. Hãy tìm mã liên quan ở đây:

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

Mã vá có liên quan (sao chép từ github) cho rest.py là ở đây:

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

Tính đến tháng 4 năm 2016, không ai trong số những gợi ý khác làm việc . (Dropbox API phiên bản 2, Python SDK phiên bản 6.2).

Nếu bạn chỉ cần một vài trong số các chức năng SDK, tôi tìm thấy nó dễ dàng nhất để chỉ cần sử dụng các API HTTP trực tiếp:

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)