Используйте представления Django для обработки загрузок в Blobstore - PullRequest
2 голосов
/ 11 февраля 2012

Вместо использования BlobstoreUploadHandler, поставляемого в AppEngine, я бы предпочел использовать представление Django, чтобы я мог хранить все URL и функции просмотра вместе.Однако я не могу узнать, как получить blob-key загруженного файла!(как get_uploads () делает для обработчика загрузки).Я видел, что BlobstoreUploadHandler использует request.params , но я не думаю, что это доступно из Request Джанго.

def upload_form(request):
    upload_url = blobstore.create_upload_url(reverse(upload_blob))
    output = '<html><body>'
    output += '<form action="%s" method="POST" enctype="multipart/form-data">' % upload_url)
    output += ('''Upload File: <input type="file" name="file"><br> <input type="submit"
        name="submit" value="Submit"> </form></body></html>''')

def upload_blob(request):
    print request
    # How to get the 'blob-key' from request?!

Когда я проверяю объект запроса, все, что я получаю, это

<WSGIRequest
GET:<QueryDict: {}>,
POST:<QueryDict: {u'submit': [u'Submit']}>
# And COOKIES, META, etcetera

РЕДАКТИРОВАТЬ: Request.FILES

Я обнаружил, что некоторую информацию можно извлечь с помощью запроса.FILES, что дает:

<MultiValueDict: {u'file': [<InMemoryUploadedFile: my_file (message/external-body)>]}>

Тем не менее, я предполагаю, что хранилище BLOB-объектов по-прежнему обрабатывает содержимое файла (поэтому оно говорит "content_type = message / external-body"?), Поэтому мне все еще нужноключ как-то.Вызов read () дает:

Content-Type: application/octet-stream
MIME-Version: 1.0
Content-Length: 17
Content-MD5: ZmQ3OTJhNjMzNGE0OTAzNGU4NjE5MDNmMGEwNjliMGE=
content-type: application/octet-stream
content-disposition: form-data; name="file"; filename="a1_blob"
X-AppEngine-Upload-Creation: 2012-02-12 22:11:49.643751

Таким образом, похоже, что AppEngine фактически заменил содержимое файла этим дескриптором, но все же, где AppEngine помещает ключ?

Я начинаю подозревать, что ключ blob просто теряется, когда не используется инфраструктура webapp, так как объект UploadedFile не имеет метода key ().

Ответы [ 4 ]

1 голос
/ 31 августа 2015

Ключевая информация не находится непосредственно в файле, она находится в file.blobstore_info.key()

  1. отправьте вашу форму, содержащую ваше изображение, на URL, созданный с помощью blobstore.create_upload_url():

    from google.appengine.ext import blobstore
    
    upload_url = blobstore.create_upload_url('/add_image/')
    

созданный URL сохранит изображение в blobstore и перенаправит запрос (с измененным объектом файла) на /add_image/

определить шаблон URL и представление для /add_image/ и обработать изображение:

def add_action_image(request):
    image = request.data.get('image')
    image_key = image.blobstore_info.key()
    ... addl' logic to save a record with the image_key...
1 голос
/ 13 февраля 2012

Мне потребовалось много времени, чтобы найти, но content_type: message/external-body требует дополнительных параметров, чтобы найти файл фактический , в случае AppEngine это blob-key.Однако Django не поддерживает эти дополнительные параметры content_type, поэтому они действительно теряются в процессе.Кажется, есть патч, но я не думаю, что он есть в версии AppEngine Django.

https://code.djangoproject.com/ticket/13721

1 голос
/ 13 февраля 2014

У меня вчера была такая же проблема.Благодаря вашему посту я понял, что проблема была в Джанго и его классовых взглядах.Я наконец-то использую код, который у меня есть с 2011 года, и он все еще работает.Он не использует BlobstoreUploadHandler, но он получает blob_infos из запроса после автоматической загрузки его в blobstore.

Вы можете использовать эту функцию следующим образом из функции или класса обратного вызова django (я, наконец, не пробовал егов представлении класса из Django, но я думаю, что это будет работать. В настоящее время я использую его в представлении функции из Django с его запросом):

media_blobs = get_uploads(request, populate_post=True)

Функция следующая:

import cgi 
from google.appengine.ext import blobstore
def get_uploads(request, field_name=None, populate_post=False):
    """Get uploads sent to this handler.
    Args:
    field_name: Only select uploads that were sent as a specific field.
    populate_post: Add the non blob fields to request.POST
    Returns:
      A list of BlobInfo records corresponding to each upload.
      Empty list if there are no blob-info records for field_name.
    """

    if hasattr(request,'__uploads') == False:
        request.META['wsgi.input'].seek(0)
    ja = request.META['wsgi.input']
    fields = cgi.FieldStorage(request.META['wsgi.input'], environ=request.META)

    request.__uploads = {}
    if populate_post:
        request.POST = {}

    for key in fields.keys():
        field = fields[key]
        if isinstance(field, cgi.FieldStorage) and 'blob-key' in field.type_options:
            request.__uploads.setdefault(key, []).append(blobstore.parse_blob_info(field))
        elif populate_post:
            if isinstance(field, list):
                request.POST[key] = [val.value for val in field]
            else:
                request.POST[key] = field.value
    if field_name:
        try:
            return list(request.__uploads[field_name])
        except KeyError:
            return []
    else:
        results = []
        for uploads in request.__uploads.itervalues():
            results += uploads
        return results

Последняя функция не моя.Я не помню, где я получил это три или четыре года назад.Но я думаю, что это кому-то поможет.

ОБНОВЛЕНИЕ:

Вы также можете использовать обработчик представления webapp.WSGIApplication и одновременно использовать django.Этот способ позволит вам использовать BlobstoreUploadHandler и BlobstoreDownloadHandler (например, для видеопотока).Вам нужно только добавить класс представления в main.py и создать его обработчик:

class ServeVideoHandler(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, resource):
        ...

downloader_handler = webapp.WSGIApplication([('/pathA/pathB/([A-Za-z0-9\-\=_]+)', ServeVideoHandler),], debug=True)

А в app.yaml добавить обработчик перед сценарием main.application, содержащим ваше приложение django.

- url: /pathA/pathB/(.+)
  script: main.downloader_handler
0 голосов
/ 12 февраля 2012

Как вы заметили, BlobstoreUploadHandler является открытым исходным кодом, поэтому вы можете увидеть логику, которую они используют для анализа ключа из параметров запроса.Обратите внимание, что request.params содержит только переменные из строки запроса и тела запроса (для запросов POST).Поэтому вы можете начать с объекта REQUEST вашего запроса djnago.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...