将获取的图像存储到Blobstore

时间:2014-02-24 15:19:10

标签: google-app-engine blobstore

我使用python google app引擎的urlfetch api从网址中提取了一个图片文件。

img = urlfetch.fetch(url).content

我想将其上传到blobstore,以便能够将其提供给用户。因此,我愿意将blob_key保存到数据存储区。正如Google App Engine Blobstore的文档中所述,我不想为用户创建上传页面,因为这项工作将在服务器端完成。

实现这一目标的步骤应该是什么?

2 个答案:

答案 0 :(得分:2)

不推荐使用blobstore的fileapi,因此您需要上传到云存储而不是blobstore。

import cloudstorage as gcs

filename = "<your bucket + filename>"   
with gcs.open(filename, 'w') as f:
    f.write(img)
blobstore_filename = "/gs"+filename
#this is needed if you want to continue using blob_keys.
return blobstore.BlobKey(blobstore.create_gs_key(blobstore_filename))

请参阅gcs here

的文档

答案 1 :(得分:2)

更新随着app engine 1.9.0的到来,应用程序可以使用默认的GCS存储桶,它提供已配置的存储桶免费配额!

更多详情here

您还可以将多部分表单发送到blobstore upload_url。

这是我将blob上传到blobstore的代码:

from __future__ import unicode_literals

import webapp2
import mimetypes
import logging
from google.appengine.ext.ndb import blobstore                                                      
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.api import urlfetch
from google.appengine.runtime import DeadlineExceededError

CRLF = b'\r\n'
BOUNDERY = b'--Th15-Is-ThE-BoUnDeRy--'


def _encode_multipart(_fields=None, _files=None):
    """ Generator inserts fields and files to create a multipart payload """

    for (field_name, field_value) in _fields or []:
        yield b'--' + BOUNDERY + CRLF
        yield b'Content-Disposition: form-data; name="%s"' % str(field_name) + CRLF
        yield CRLF
        yield str(field_value) + CRLF

    for (file_name, file_data) in _files or []:
        yield b'--' + BOUNDERY + CRLF
        yield b'Content-Disposition: form-data; name="file"; filename="%s"' \
              % str(file_name) + CRLF
        yield b'Content-Type: %s' % mimetypes.guess_type(file_name)[0] + CRLF
        yield CRLF
        yield file_data + CRLF

    yield b'--%s--' % BOUNDERY + CRLF


def create_upload_url(for_url):

    return blobstore.create_upload_url(for_url, max_bytes_per_blob=1048576)


def _fetch_blob_update(payload):

    upload_url = create_upload_url(webapp2.uri_for('blob_update', _full=True))
    try:
        response = urlfetch.fetch(
            url=upload_url,
            payload=payload,
            method=urlfetch.POST,
            deadline=40,
            follow_redirects=False,
            headers={b'Content-Type': str('multipart/form-data; boundary=%s' % BOUNDERY)}
        )
        if response.status_code != 200:
            logging.error('URL : %s fetch ERROR : %d' % (upload_url, response.status_code))
            return None
        else:
            return response.content
    except (urlfetch.DownloadError, DeadlineExceededError), e:
        logging.error('fetch %s download or deadline error, exception : %s'
                      % (upload_url, str(e)))
        return None


def blob_update_by_upload(ndb_key, blob):
    """ update blob using upload to the blobstore """

    result = _fetch_blob_update(b''.join(_encode_multipart(_files=[(ndb_key.id(), blob)])))
    return blobstore.BlobKey(result)


class BlobUpdate(blobstore_handlers.BlobstoreUploadHandler):
    """ has named route : blob_update """

    def post(self):
        """ blob upload handler returns the new blobkey """

        blob_info = self.get_uploads('file')[0]
        self.response.headers[b'Content-Type'] = b'text/plain'
        self.response.write(str(blob_info.key()))

路线:

webapp2.Route(r'/blob_update', handler='....BlobUpdate', name='blob_update')