我使用python google app引擎的urlfetch api从网址中提取了一个图片文件。
img = urlfetch.fetch(url).content
我想将其上传到blobstore,以便能够将其提供给用户。因此,我愿意将blob_key保存到数据存储区。正如Google App Engine Blobstore的文档中所述,我不想为用户创建上传页面,因为这项工作将在服务器端完成。
实现这一目标的步骤应该是什么?
答案 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')