Planuję stworzyć aplikację internetową, która umożliwi użytkownikom obniżanie wersji plików projektów Visual Studio. Wygląda jednak na to, że Google App Engine akceptuje przesyłanie plików i przechowywanie prostych plików na serwerze Google za pośrednictwem db.TextProperty
i db.BlobProperty
.
Cieszę się, że każdy może dostarczyć przykładowy kod (zarówno po stronie klienta, jak i po stronie serwera), w jaki sposób można to zrobić.
python
google-app-engine
Graviton
źródło
źródło
Odpowiedzi:
Oto kompletny, działający plik. Wyciągnąłem oryginał z witryny Google i zmodyfikowałem go, aby był nieco bardziej prawdziwy.
Kilka rzeczy, na które należy zwrócić uwagę:
Celem tej linii w klasie ServeHandler jest "naprawienie" klucza tak, aby pozbył się wszelkich zmian nazw, które mogły wystąpić w przeglądarce (nie zauważyłem żadnego w Chrome)
blob_key = str(urllib.unquote(blob_key))
Klauzula „save_as” na końcu tego jest ważna. Zapewni to, że nazwa pliku nie zostanie zniekształcona, gdy zostanie wysłany do przeglądarki. Pozbądź się go, aby obserwować, co się dzieje.
self.send_blob(blobstore.BlobInfo.get(blob_key), save_as=True)
Powodzenia!
import os import urllib from google.appengine.ext import blobstore from google.appengine.ext import webapp from google.appengine.ext.webapp import blobstore_handlers from google.appengine.ext.webapp import template from google.appengine.ext.webapp.util import run_wsgi_app class MainHandler(webapp.RequestHandler): def get(self): upload_url = blobstore.create_upload_url('/upload') self.response.out.write('<html><body>') self.response.out.write('<form action="%s" method="POST" enctype="multipart/form-data">' % upload_url) self.response.out.write("""Upload File: <input type="file" name="file"><br> <input type="submit" name="submit" value="Submit"> </form></body></html>""") for b in blobstore.BlobInfo.all(): self.response.out.write('<li><a href="https://stackoverflow.com/serve/%s' % str(b.key()) + '">' + str(b.filename) + '</a>') class UploadHandler(blobstore_handlers.BlobstoreUploadHandler): def post(self): upload_files = self.get_uploads('file') blob_info = upload_files[0] self.redirect('/') class ServeHandler(blobstore_handlers.BlobstoreDownloadHandler): def get(self, blob_key): blob_key = str(urllib.unquote(blob_key)) if not blobstore.get(blob_key): self.error(404) else: self.send_blob(blobstore.BlobInfo.get(blob_key), save_as=True) def main(): application = webapp.WSGIApplication( [('/', MainHandler), ('/upload', UploadHandler), ('/serve/([^/]+)?', ServeHandler), ], debug=True) run_wsgi_app(application) if __name__ == '__main__': main()
źródło
self.__uploads
wblobstore_handler
toNone
, kiedy próbuję to.W rzeczywistości odpowiedź na to pytanie znajduje się w dokumentacji App Egnine. Zobacz przykład przesyłania obrazów użytkowników .
Kod HTML wewnątrz <form> </form>:
Kod Pythona:
źródło
W Grupach dyskusyjnych Google jest na ten temat wątek:
Przesyłanie plików
Dzięki dużej ilości przydatnego kodu dyskusja ta bardzo pomogła mi w przesyłaniu plików.
źródło
Firma Google udostępniła usługę do przechowywania dużych plików. Zapoznaj się z dokumentacją interfejsu API blobstore . Jeśli Twoje pliki mają rozmiar> 1 MB, powinieneś go użyć.
źródło
Dziś próbuję, działa następująco:
moja wersja sdk to 1.3.x
strona html:
<form enctype="multipart/form-data" action="/upload" method="post" > <input type="file" name="myfile" /> <input type="submit" /> </form>
Kod serwera:
file_contents = self.request.POST.get('myfile').file.read()
źródło
Jeśli nadal masz problem, sprawdź, czy używasz enctype w tagu formularza
Nie:
<form encoding="multipart/form-data" action="/upload">
Tak:
<form enctype="multipart/form-data" action="/upload">
źródło
Nie można przechowywać plików, ponieważ nie ma tradycyjnego systemu plików. Możesz je przechowywać tylko w ich własnym DataStore (w polu zdefiniowanym jako BlobProperty )
W poprzednim linku znajduje się przykład:
class MyModel(db.Model): blob = db.BlobProperty() obj = MyModel() obj.blob = db.Blob( file_contents )
źródło
Osobiście uważam, że samouczek opisany tutaj jest przydatny podczas używania środowiska wykonawczego Java z GAE. Z jakiegoś powodu, gdy próbowałem przesłać plik przy użyciu
<form action="/testservelet" method="get" enctype="multipart/form-data"> <div> Myfile:<input type="file" name="file" size="50"/> </div> <div> <input type="submit" value="Upload file"> </div> </form>
Okazało się, że moja klasa HttpServlet z jakiegoś powodu nie akceptuje formularza z atrybutem „enctype”. Usunięcie go działa, jednak oznacza to, że nie mogę przesłać żadnych plików.
źródło
W Google App Engine nie ma przechowywania plików płaskich. Wszystko musi trafić do Datastore, który jest trochę jak relacyjna baza danych, ale nie do końca.
Pliki można przechowywać jako atrybuty TextProperty lub BlobProperty .
Istnieje limit 1 MB na wpisy DataStore, co może, ale nie musi, stanowić problem.
źródło
Zauważyłem dziwne zachowanie podczas przesyłania plików do App Engine. Przesyłając następujący formularz:
<form method="post" action="/upload" enctype="multipart/form-data"> <input type="file" name="img" /> ... </form>
A następnie wyodrębniasz
img
z żądania w ten sposób:img_contents = self.request.get('img')
img_contents
Zmienna jeststr()
w Google Chrome, ale to unicode w Firefoksie. I tak jak teraz,db.Blob()
konstruktor pobiera ciąg znaków i zgłasza błąd, jeśli przekażesz łańcuch znaków Unicode.Czy ktoś wie, jak można to naprawić?
Co więcej, wydaje mi się absolutnie dziwne, że kiedy kopiuję i wklejam aplikację Księga gości (z awatarami), działa idealnie. Robię wszystko dokładnie tak samo w swoim kodzie, ale to po prostu nie zadziała. Jestem już blisko wyrywania włosów.
źródło
Istnieje sposób wykorzystania płaskiego systemu plików (przynajmniej w perspektywie użytkowej)
Jest to projekt wirtualnego systemu plików Google App Engine . który jest implementowany przy pomocy interfejsów API datastore i memcache w celu emulacji zwykłego systemu plików. Korzystając z tej biblioteki, możesz użyć w swoim projekcie podobnego dostępu do systemu plików (odczyt i zapis) .
źródło