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].
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en.

Reply via email to