Gestori dell'archivio Blobstore webapp

webapp include classi di gestori delle richieste per lavorare con l'API Blobstore. BlobstoreUploadHandler fornisce la logica per analizzare la richiesta di caricamento passata tramite il Blobstore nei record BlobInfo per l'ulteriore elaborazione. BlobstoreDownloadHandler semplifica la pubblicazione dei valori dell'archivio BLOB da qualsiasi percorso.

BlobstoreUploadHandler

I valori vengono aggiunti all'archivio BLOB tramite i caricamenti di file pubblicati dagli utenti o dagli amministratori dell'app. L'app pubblica un modulo web con un campo per il caricamento di file e un'azione del modulo che indirizza il caricamento all'archivio BLOB. L'app ottiene l'URL dell'azione del modulo chiamando una funzione (create_upload_url()), passando l'URL di un gestore di app che viene chiamato quando gli utenti caricano file. Un'applicazione web può utilizzare una sottoclasse della classe BlobstoreUploadHandler come gestore per questo URL.

Il metodo get_uploads() restituisce un elenco di oggetti BlobInfo, uno per ogni file caricato nella richiesta. Ogni oggetto contiene la chiave dell'archivio BLOB per il valore caricato, nonché metadati come il nome file e le dimensioni. Ogni file caricato ha anche un'entità corrispondente nel datastore con queste informazioni, quindi puoi recuperare l'oggetto BlobInfo in un secondo momento una volta specificata una chiave blob oppure eseguire una query sul datastore sui campi dei metadati. Il gestore di caricamento analizza queste informazioni direttamente dai dati della richiesta, non dal datastore.

Per impostazione predefinita, get_uploads() restituisce oggetti BlobInfo per tutti i file caricati nella richiesta. Il metodo accetta anche un argomento field_name per ottenere solo il file (o i file) per un determinato campo di caricamento file. Il valore restituito è sempre un elenco, possibilmente vuoto.

class PhotoUploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        upload = self.get_uploads()[0]
        user_photo = UserPhoto(
            user=users.get_current_user().user_id(),
            blob_key=upload.key())
        user_photo.put()

        self.redirect('/view_photo/%s' % upload.key())

Utilizzo di BlobstoreUploadHandler con Google Cloud Storage

Se utilizzi questo gestore di caricamento con Cloud Storage, dovrai recuperare e archiviare il nome completo del file dell'oggetto di Cloud Storage, poiché questa operazione è necessaria per recuperare nuovamente il file da Cloud Storage. Utilizza la funzione get_file_infos, che restituisce un elenco di record FileInfo corrispondenti a ciascun caricamento. Il nome completo dell'oggetto di Cloud Storage, il tipo di contenuto, l'ora di creazione e altri dati sono disponibili in FileInfo. (Per informazioni dettagliate, visita il link.)

BlobstoreDownloadHandler

Per pubblicare un valore dell'archivio BLOB, l'applicazione imposta l'intestazione X-AppEngine-BlobKey sul valore di una chiave dell'archivio BLOB in formato stringa. Quando App Engine vede questa intestazione nella risposta, fornisce il valore del blob come corpo della risposta. La classe di gestore di app web BlobstoreDownloadHandler semplifica l'impostazione di questo valore nella risposta.

Il metodo send_blob() prende un oggetto BlobKey, una chiave stringa o un BlobInfo come argomento blob_key_or_info e imposta i dati di risposta in modo che il valore del blob venga mostrato all'utente. Il metodo utilizza un argomento facoltativo content_type che sostituisce il tipo di contenuto MIME del valore del blob archiviato. Per impostazione predefinita, il blob viene pubblicato con il tipo di contenuto impostato dal client che lo ha caricato, un tipo di contenuto derivato dal nome del file o un tipo generico se non sono disponibili altri tipi di informazioni.

Il metodo send_blob() accetta un argomento save_as che determina se i dati del blob vengono inviati come dati di risposta non elaborati o come allegato MIME con un nome file. Se l'argomento è una stringa, il blob viene inviato come allegato e il valore della stringa viene utilizzato come nome del file. Se True e blob_key_or_info sono un oggetto BlobInfo, viene utilizzato il nome file dell'oggetto. Per impostazione predefinita, i dati del blob vengono inviati come corpo della risposta e non come allegato MIME.

class ViewPhotoHandler(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, photo_key):
        if not blobstore.get(photo_key):
            self.error(404)
        else:
            self.send_blob(photo_key)

L'archivio BLOB supporta l'invio solo di una parte di un valore anziché del valore completo, descritto come un intervallo di indici di byte. Puoi fornire un intervallo di indice di byte al metodo send_blob() di BlobstoreDownloadHandler in due modi. Il primo è specificare l'intervallo come argomenti start e end:

            # Send the first 1,000 bytes of the value.
            self.send_blob(key, start=0, end=999)

Per impostazione predefinita, BlobstoreDownloadHandler rispetta l'intestazione range nella richiesta. Se vuoi bloccare l'uso dell'intestazione dell'intervallo originale, fornisci il parametro use_range=False a send_blob():

            # Send the full value of the blob and
            # block the "range" header.
            self.send_blob(key, use_range=False)

Il valore dell'intestazione range è un intervallo di byte HTTP standard. BlobstoreDownloadHandler utilizza webob.byterange per analizzare questo valore di intestazione.

Completa l'applicazione di esempio

Nella seguente applicazione di esempio, l'URL principale dell'applicazione carica il modulo che richiede all'utente un file da caricare e il gestore del caricamento chiama immediatamente il gestore dei download per fornire i dati. Questo serve a semplificare l'applicazione di esempio. In pratica, probabilmente non useresti l'URL principale per richiedere i dati di caricamento, né pubblicheresti immediatamente un blob che avevi appena caricato.

from google.appengine.api import users
from google.appengine.ext import blobstore
from google.appengine.ext import ndb
from google.appengine.ext.webapp import blobstore_handlers
import webapp2


# This datastore model keeps track of which users uploaded which photos.
class UserPhoto(ndb.Model):
    user = ndb.StringProperty()
    blob_key = ndb.BlobKeyProperty()


class PhotoUploadFormHandler(webapp2.RequestHandler):
    def get(self):
        upload_url = blobstore.create_upload_url('/upload_photo')
        # To upload files to the blobstore, the request method must be "POST"
        # and enctype must be set to "multipart/form-data".
        self.response.out.write("""
<html><body>
<form action="{0}" method="POST" enctype="multipart/form-data">
  Upload File: <input type="file" name="file"><br>
  <input type="submit" name="submit" value="Submit">
</form>
</body></html>""".format(upload_url))


class PhotoUploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        upload = self.get_uploads()[0]
        user_photo = UserPhoto(
            user=users.get_current_user().user_id(),
            blob_key=upload.key())
        user_photo.put()

        self.redirect('/view_photo/%s' % upload.key())


class ViewPhotoHandler(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, photo_key):
        if not blobstore.get(photo_key):
            self.error(404)
        else:
            self.send_blob(photo_key)


app = webapp2.WSGIApplication([
    ('/', PhotoUploadFormHandler),
    ('/upload_photo', PhotoUploadHandler),
    ('/view_photo/([^/]+)?', ViewPhotoHandler),
], debug=True)