2012-02-19 12 views
15

Próbuję tworzyć pliki w folderze Dropbox.com z aplikacji GAE. Wykonałem wszystkie kroki rejestrując aplikację Dropbox i zainstalowałem Python SDK z Dropbox lokalnie na mojej maszynie programistycznej. (patrz interfejs API dropbox.com). Wszystko działa idealnie, gdy korzystam ze skryptu testowego cli_client.py w pakiecie SDK na moim komputerze lokalnym, aby uzyskać dostęp do skrzynki referencyjnej - mogę "umieścić" pliki itp.Zapisywanie plików na koncie Dropbox z GAE

Chcę teraz rozpocząć pracę w środowisku GAE, więc rzeczy się trochę trudne. Przydałaby się pomoc.

Dla obeznanych z kodem Dropbox API, miałem następujące zagadnienia dotąd:

Issue 1

rest.py Dropbox moduł API używa pkg_resources aby uzyskać certs witryny-zainstalowane w pakiety instalacji komputera lokalnego. Wymieniłem

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

z

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

i umieszcza plik cert w moim katalogu aplikacji GAE. Być może nie jest to w porządku; zobacz mój kod błędu uwierzytelniania poniżej.

Issue 2

session.py Dropbox moduł API używa OAuth modułu, więc zmieniłem to do AppEngine OAuth.

Ale podniósł wyjątek, że oauth GAE nie ma metody OAuthConsumer używanej przez moduł sesyjny Dropbox session.py. Więc ściągnąłem oauth 1.0 i dodałem do mojej aplikacji a teraz zaimportuję to zamiast GAEA oauth.

Issue 3

GAE moduł SSL nie wydaje się mieć CERT_REQUIRED nieruchomości.

To jest stała, więc zmieniłem

self.cert_reqs = ssl.CERT_REQUIRED 

do

self.cert_reqs = 2 

ten jest wykorzystywany podczas wywoływania

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

Authentication Error

Ale nadal nie może połączyć się z 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

Mam nadzieję, że ktoś odpowiada na to. W międzyczasie, chociaż nie jestem pewien, co to jest pkg_resources.resource_filename(), myślę, że zwraca nazwę pliku, a nie otwarty plik, podczas gdy file() otwiera podany plik i zwraca obiekt strumienia (otwarty plik). Zamiast tego możesz wypróbować 'TRUSTED_CERT_FILE = 'trusted-certs.crt''. –

+0

Dzięki Guido - spróbujmy tego, – erickCo

+0

Guido, masz rację, typ zwracany przez 'pkg_resources.resource_filename()' to 'str'. Wartością jest pełna ścieżka do pliku certyfikatów. Więc wprowadziłem zmianę, jak sugerujesz. Niestety, wciąż ten sam błąd. – erickCo

Odpowiedz

7

Oto mój połatany wersja Dropbox Python SDK 1.4, która działa dobrze dla mnie z Python 2.7 GAE: dropbox_python_sdk_gae_patched.7z.base64. Żadne dodatkowe biblioteki stron trzecich nie były potrzebne, tylko te dostarczane przez środowisko GAE.

Testowane jest tylko przesyłanie plików (put_file). Oto etapy konfiguracji:

  1. Rozpakuj archiwum do folderu głównego aplikacji GAE (jeśli główna aplikacja znajduje się w folderze głównym). Możesz dekodować BASE64 używając Base64 Encoder/Decoder: base64.exe -d dropbox_python_sdk_gae_patched.7z.base64 dropbox_python_sdk_gae_patched.7z.
  2. Konfiguracja APP_KEY, APP_SECRET, ACCESS_TYPE, ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET. Pierwsze trzy są skonfigurowane w czasie tworzenia aplikacji Dropbox. Ostatnie dwie zostały uzyskane przy przyznawaniu aplikacji dostępu do określonego konta Dropbox, można je pobrać przez cli_client.py (z DB Python SDK) z pliku token_store.txt.
  3. Zastosowanie w kodzie jak poniżej:

    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

Czy możesz zaktualizować to do najnowszej wersji sdk Dropbox, tej, która ma DropboxOAuth2FlowNoRedirect? –

3

pomyślnie przesłany z Google App Engine do Dropbox z własną poprawiona wersja z Dropbox SDK: https://github.com/cklein/dropbox-client-python

Wykorzystanie urllib2 zastąpiono huTools.http: https://github.com/hudora/huTools/

Jest to kod, który nazywa się w przewodnika żądanie:

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

Mam połatany z Dropbox Python SDK w wersji 2.2 do pracy na Google App Engine. Proszę znaleźć odpowiedni kod tutaj:

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

Stosowna poprawka kodu (skopiowany z github) dla rest.py jest tutaj:

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

W kwietniu 2016 roku, żaden z pozostałych propozycji pracy . (Dropbox API w wersji 2, Python SDK w wersji 6.2).

Jeśli trzeba tylko niektóre z funkcji SDK, znalazłem to najłatwiej po prostu korzystać z API HTTP bezpośrednio:

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) 
Powiązane problemy