Hi Iap,

Have you seen my series of blog posts about handling uploads to the
blobstore?

http://blog.notdot.net/tag/blobstore

-Nick Johnson

On Sun, Jan 16, 2011 at 11:08 PM, Iap <[email protected]> wrote:

> HI, Nick
> Thanks for your reply, I have fired a feature request in the tracking
> system.
>
> After several days survey, I have completed a not prefect workaround for
> multiple uploading.
> Hope this will help to those people with the same issue before the official
> solution.
>
> The workaround is based on uploadify(http://www.uploadify.com/), the idea
> is:
> 1. Requests the create_upload_url() with the "onCheck" event of uploadify.
>     The create_upload_url() has to be called many times to create several
> sessions if multiple files will be uploaded.
>
> 2. Because the uploadify does not send cookie with the uploading request,
> if the action url requires login, the authentication will be failed. In
> order to recover the user object later, the user instance's key has to be
> passed in the redirected url (as well as extra data of validation to protect
> from cracking).
>
> 3. Update the url of action in every uploadify onComplete or onError event.
> This will consume the urls gotten in the step 1.
>
> 4. In the handler which is redirected from the
> blobstore.create_upload_url(), verify the protection data if any, then
> recover the instance concerns to the user and handles the blobinfo.
>
> There are the example codes:
>
> In javascript:
>             $('#file_upload').uploadify({
>                 'script'    : '', // will be assigned later
>                 'auto'      : true,
>                 'multi': true,
>
>  'checkScript':'url_to_handler_which_calls_create_upload_url()',
>                 'onCheck'  : function(event,data,key) {
>                             var urls =
> $('#file_upload').data('upload_urls')
>                             urls = urls.concat(data.data)
>                             var url = urls.shift()
>                             $('#file_upload').data('upload_urls',urls)
>
>  $('#file_upload').uploadifySettings('script',url)
>                             return false
>                     },
>                 'onComplete':function (event, ID, fileObj, response, data){
>                     var urls = $('#file_upload').data('upload_urls')
>                     var url = urls.shift()
>                     $('#file_upload').data('upload_urls',urls)
>                     if (!url) {
>                         return
>                     }
>                     $('#file_upload').uploadifySettings('script',url)
>                 },
>                 'onError':function(event,ID,fileObj,errorObj) {
>                     var urls = $('#file_upload').data('upload_urls')
>                     var url = urls.shift()
>                     if (!url) {
>                         // the last uploading causes error
>                         return
>                     }
>                     $('#file_upload').data('upload_urls',urls)
>                     $('#file_upload').uploadifySettings('script',url)
>                 }
>             });
>
> in GAE handler:
>
> ##
> ## handles the url_to_handler_which_calls_create_upload_url()
> ## (this is implementation specific)
> ##
> class ResourceUploadHandler(blobstore_handlers.BlobstoreUploadHandler):
>
>     ## because the uploadify do the onCheck with javascript,
>     ## the cookie will be sent, so it can be sure that
>     ## get_current_user() is not None.
>     def get_urls(self,n):
>         user = users.get_current_user()
>         assert user
>         ## remember to add extra validation data
>         success_path ='resource/upload/'?email=%s' % (user.email)
>         upload_urls = []
>         for i in range(0,n):
>             upload_urls.append( blobstore.create_upload_url(success_path) )
>         if n==1:
>             upload_urls = upload_urls[0]
>         return json(upload_urls)
>
>     ## The "post" will be called twice, firstly for checking,
>     ## then for uploading actual data. This is not required,
>     ## you can separate into two individual handlers of course.
>
>     ## Because the uploadify do uploading with Flash,
>     ## it does not send cookie when uploading file data,
>     ## the login_required will be failed.
>     #@login_required
>     def post(self):
>         blobinfos = []
>         for blobinfo in self.get_uploads():
>             blobinfos.append(blobinfo)
>         if not blobinfos:
>             ## requested by "onCheck" of uploadify,
>             n = len(self.request.form.keys())
>             ## excludes the extra key -- "folder"
>             return self.get_urls(n - 1)
>
>         ## here comes the actual uploading
>         ## do validation here to protect from cracking
>         #data_to_verify = self.request.args.get('extra_data')
>         #do_the_verification(data_to_verify)
>
>         ## do the job
>         email = self.request.args.get('email')
>         user_entity =  retrive_the_user_entity_from_email(email)
>         for blobinfo in blobinfos:
>             whatever_you_like_to_do_with(blobinfo)
>
> iap
>
> 2011/1/12 Nick Johnson (Google) <[email protected]>
>
> Hi Iap,
>>
>> Unfortunately, the blobstore doesn't currently support this use-case. We
>> may add support for invariant upload URLs and alternate encapsulation
>> methods in future - feel free to file a feature request in the issue
>> tracker!
>>
>> -Nick Johnson
>>
>> On Wed, Jan 12, 2011 at 3:54 PM, Iap <[email protected]> wrote:
>>
>>> Hi,
>>> The official API requires two steps to create an entry in blobstore.
>>> Firstly, get an URL by create_upload_url(), then receive the BlobKey in
>>> redirected handler.
>>>
>>> That doesn't fit into my case. Because:
>>> In client side, I use ajax to send data, which does not send data with
>>> "multipart/form-data",
>>> instead it sends with "X-Requested-With" header and
>>> "application/octet-stream" content-type.
>>> That is because it want to send multiple files one by one immediately,
>>> soon after user has selected the files to upload.  (see
>>> http://valums.com/ajax-upload/)
>>>
>>> The url, returned by create_upload_url() can only handles
>>> "multi-part/formdata"
>>> and reject any extra querystring , the filename goes there (ex.
>>> create_upload_url()+'?qqfile=test.jpg').
>>> So I can not create the blobstore entity by the official two-steps
>>> procedure.
>>>
>>> But I can not find any other way to create blobstore entity.
>>> Any suggestions are appreciated. Thanks in advance.
>>>
>>> iap
>>>
>>
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Google App Engine" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected]<google-appengine%[email protected]>
> .
> For more options, visit this group at
> http://groups.google.com/group/google-appengine?hl=en.
>



-- 
Nick Johnson, Developer Programs Engineer, App Engine
Google Ireland Ltd. :: Registered in Dublin, Ireland, Registration Number:
368047

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en.

Reply via email to