# urls.py
urlpatterns = patterns('',
(r'^get_blob/(?P<key>[a-zA-Z0-9_=.+-]+)?/$', 'lib.blob_import.get_blob'),
(r'^remote_display_image/(?P<blob_key>[a-zA-Z0-9_=.+-]+)/$', 'lib.blob_import.remote_display_image'),
....)
# import_job.py
# this is triggered by Cron in application on HRD
def do():
limit = 4 # 4 entities processing at once, it might be increased...
query = MyEntity.all()
holder = query.fetch(limit)
blob_import.run_fetch(holder)
while len(holder) > 0:
time.sleep(0.1)
holder = query.with_cursor(query.cursor()).fetch(limit)
blob_import.run_fetch(holder)
do()
# my models.py contains following entity definition
class MyEntity(BaseModel):
ref = db.ReferenceProperty(BaseModel)
img = blobstore.BlobReferenceProperty(verbose_name=u'Fotografie')
desc = db.StringProperty(required=False)
created_when = db.DateTimeProperty()
# blob_import.py
# main worker file
# -*- coding: utf-8 -*-
from __future__ import with_statement # Note this MUST go at the top of your views.py
from StringIO import StringIO
from google.appengine.ext import blobstore
from google.appengine.ext.blobstore.blobstore import BlobInfo
from web.models import MyEntity
import logging
def get_blob(request, key):
from django.http import HttpResponseRedirect
from django.core import urlresolvers
photo = MyEntity.get_by_id(int(key))
if photo:
info = BlobInfo(photo.img.key())
return HttpResponseRedirect(urlresolvers.reverse(remote_display_image, kwargs={'blob_key':info.key()}))
return HttpResponseRedirect(urlresolvers.reverse(remote_display_image, kwargs={'blob_key': ''}))
def handle_result(rpc, photo):
from google.appengine.api import files
if True:
fetch_response = rpc.get_result()
file_data = fetch_response.content
content_type = fetch_response.headers.get('content-type', None)
x_file_name = fetch_response.headers.get('X-file-name', None)
if x_file_name == 'NOFILE':
return
# Create the file
file_name = files.blobstore.create(mime_type=content_type, _blobinfo_uploaded_filename=x_file_name)
stream = StringIO()
stream.write(file_data)
stream.seek(0)
# Open the file and write to it
if file_name:
try:
with files.open(file_name, 'a') as f:
data = stream.read(65535)
while data:
f.write(data)
data = stream.read(65535)
stream.flush()
files.finalize(file_name)
except :
logging.debug('Error during writing file %s' % x_file_name)
else:
stream.flush()
# Get the file's blob key
blob_key = files.blobstore.get_blob_key(file_name)
if blob_key:
new_info = blobstore.BlobInfo.get(blob_key)
if new_info:
photo.img = new_info
photo.put()
else:
MyEntity.delete(photo)
def create_callback(rpc, photo):
return lambda: handle_result(rpc, photo)
def run_fetch(models):
from google.appengine.api import urlfetch
from google.appengine.ext import db
rpcs = []
for obj in models:
id = obj.key().id()
if not obj.img:
continue
nfo = blobstore.BlobInfo.get(obj.img.key()) #BlobInfo(photo.img.key())
if not nfo: # if blobinfo referenced by given obj entity already exists on HRD nothing happens, so script avoid already migrated blobs and can be run multiple times
# following url is the Master/Slave one
url = '%s%i/' % ('http://www.masterslaveappurl.cz/get_blob/', id)
rpc = urlfetch.create_rpc(deadline=240)
rpc.callback = create_callback(rpc, obj)
urlfetch.make_fetch_call(rpc, url)
rpcs.append(rpc)
for rpc in rpcs:
rpc.wait()
def remote_display_image(request, blob_key):
from django import http
if len(blob_key) > 0:
blob_info = blobstore.BlobInfo.get(blob_key)
if blob_info:
blob_file_size = blob_info.size
blob_content_type = blob_info.content_type
blob_concat = ""
start = 0
end = blobstore.MAX_BLOB_FETCH_SIZE - 1
step = blobstore.MAX_BLOB_FETCH_SIZE - 1
while start < blob_file_size:
blob_concat += blobstore.fetch_data(blob_key, start, end)
temp_end = end
start = temp_end + 1
end = temp_end + step
response = http.HttpResponse(blob_concat, mimetype=blob_content_type)
response["Cache-Control"] = "no-cache, no-store, must-revalidate, pre-check=0, post-check=0"
response['X-file-name'] = blob_info.filename.encode('utf-8')
return response
response = http.HttpResponse()
response['X-file-name'] = 'NOFILE' # when no blob is find for given key
return response
Diff to Previous Revision
--- revision 19 2011-11-04 09:52:11
+++ revision 20 2011-11-04 14:56:56
@@ -100,7 +100,7 @@
nfo = blobstore.BlobInfo.get(obj.img.key()) #BlobInfo(photo.img.key())
if not nfo: # if blobinfo referenced by given obj entity already exists on HRD nothing happens, so script avoid already migrated blobs and can be run multiple times
# following url is the Master/Slave one
- url = '%s%i/' % ('http://www.jdiakup.cz/get_blob/', id)
+ url = '%s%i/' % ('http://www.masterslaveappurl.cz/get_blob/', id)
rpc = urlfetch.create_rpc(deadline=240)
rpc.callback = create_callback(rpc, obj)
urlfetch.make_fetch_call(rpc, url)